GHSA-qp9x-wp8f-qgjj
Medium · 4.0tuf has platform-dependent delegation path matching
CVSS
4.0
EPSS
—
Published
May 28, 2026
CISA due date
—
Cloudanix analysis
On Windows, the software that checks whether an update is allowed to come from a given publisher can treat names that only differ by capital letters as the same, so a Windows machine might accept an update that should have been rejected.
- Exploitation
- Supply Chain
- Attacker needs
- None
- Complexity
- Moderate
- Impact
- Data Tampering
- Component
- Library
- Class
- Authorization Bypass
- Remediation
- Upgrade
- Effort
- Low
- Patch risk
- Low
What it actually does
python-tuf's ngclient decides whether a target path is in a delegated role's glob using DelegatedRole._is_target_in_pathpattern, which calls Python's fnmatch.fnmatch. That helper runs os.path.normcase on both the pattern and the path. On POSIX, normcase is a no-op so matching is case-sensitive and slash-preserving as the TUF specification requires. On Windows, ntpath.normcase lowercases both strings and turns '/' into '\', so the same metadata authorizes a different set of targets. A Windows client can therefore treat a path as in-role when a Linux or macOS client would reject it, breaking TUF's OS-independent authorization model and enabling an authorization bypass for delegated target paths.
Why it matters to the business
Organizations that use python-tuf to verify software, firmware, or configuration updates can get inconsistent trust decisions: Windows updaters may accept artifacts that other platforms correctly refuse. That weakens supply-chain integrity for Windows fleets, can allow a less-trusted delegated publisher to cover paths they were not granted, and creates audit and compliance gaps because the same repository is not enforced uniformly. CVSS is 4.0, the issue is not in KEV, exploit maturity is none, and it has been public for roughly four months—so widespread in-the-wild abuse is not indicated, but Windows-based update clients remain a material integrity risk until the matcher is made spec-compliant.
How an attack unfolds
An attacker who can sign under a delegated TUF role (compromised or overly broad delegation keys, a malicious or co-tenant repository, or a role limited to a glob such as packages/vendor/*.tar.gz) crafts a target path whose only difference from an unauthorized location is letter case or slash style. A Windows python-tuf ngclient lowercases and backslash-normalizes both the delegation glob and the target path before fnmatch, so the path is treated as authorized. The client then accepts metadata and payload for that target as if the delegated role were allowed to sign it, violating the TUF path-pattern rules that POSIX clients still enforce. The attacker’s content is installed or cached as a trusted update only on Windows. No named threat actors or KEV/ransomware use are associated with this issue.
How to fix it
Upgrade python-tuf to a release that matches delegation globs in a platform-independent, TUF-spec-compliant way (do not use fnmatch.fnmatch / os.path.normcase for authorization). Input does not list affected packages or patched versions, so inventory every dependency and pin/upgrade as soon as the maintainer publishes a fix; until then, do not use Windows as the trust-decision host for TUF updates, or run the updater in a POSIX environment. Review repository delegations so overlapping globs cannot be confused by case folding, keep delegated keys tightly scoped, and prefer POSIX-style lowercase paths with forward slashes only. Do not implement a local workaround that still calls fnmatch.fnmatch on Windows.
How to confirm the fix worked
Enumerate deployments and lockfiles for python-tuf / tuf ngclient and record the installed version against the first patched release once published. On a Windows test client, attempt to resolve a target whose path differs from a delegated path_pattern only by ASCII case or '/' vs '\'; a fixed client must deny it, matching POSIX behavior. Confirm unit tests cover mixed-case and mixed-separator paths and that DelegatedRole._is_target_in_pathpattern no longer routes through os.path.normcase. Repositories should be scanned for duplicate targets that collide under case-insensitive comparison.
Typical attack path
- Gain the ability to publish TUF targets and metadata under a delegated role whose path_patterns are supposed to be a strict subset of the repository.
- Choose a victim path that the TUF spec would not grant to that role, but that becomes identical to an allowed glob after Windows ntpath.normcase (case fold and '/' to '\').
- Publish a target (and matching targets/snapshot/timestamp metadata) using that case- or separator-variant path.
- Wait for or induce a Windows host running vulnerable python-tuf ngclient to refresh and download.
- The client authorizes the path via fnmatch.fnmatch after normcase, verifies signatures under the wrong delegation, and materializes the attacker-controlled artifact.
- The host consumes the artifact as a trusted update, binary, or config, which POSIX clients of the same repository would have rejected.
How to detect it
This is a client-side authorization logic bug with no public exploit tooling or named actors, so there is no reliable network signature of exploitation. Hunt on Windows TUF clients for successful target fetches whose paths differ from configured delegation globs only by case or separator, and compare allow/deny outcomes with a POSIX client against the same metadata. Review TUF metadata (root, targets, delegated targets) for near-duplicate target paths, mixed-case paths, or backslashes in path fields. Inspect updater logs, caches, and downloaded artifact names for paths that collide under case folding. Sudden Windows-only acceptance of a target that Linux clients reject is the primary artifact of abuse.
What your security team should do
- Inventory Windows hosts and CI images that run python-tuf ngclient and treat them as the in-scope exposure until a patched release is deployed.
- Apply the vendor fix as soon as a version is published; there is no KEV due date, but do not leave Windows updaters on an unfixed matcher.
- Until patched, perform TUF refresh and verification on POSIX, or block production update trust decisions on Windows python-tuf.
- Audit delegated path_patterns and keys for roles that would become more powerful under case-insensitive matching.
- Add regression tests that the same metadata yields identical allow/deny results on Windows and Linux.
- Monitor python-tuf/TUF advisories; exploit maturity is none, so prioritize by Windows update-path criticality rather than mass exploitation.
The record
`DelegatedRole._is_target_in_pathpattern` uses `fnmatch.fnmatch` to decide whether a given target path is authorized by a delegation's glob pattern. Python's `fnmatch.fnmatch` calls `os.path.normcase()` on both arguments before matching. On POSIX hosts `normcase` is the identity function; on Windows hosts `os.path` resolves to `ntpath`, whose `normcase` lowercases its input and replaces `/` with `\`. As a result, python-tuf's delegation *path pattern* matching is case-sensitive on Linux/macOS but case-INSENSITIVE on Windows. This makes the authorization decision for a target dependent on the host operating system of the client running the updater. The result on Windows is a TUF specification violation in the python-tuf `ngclient` implementation.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|
Related vulnerabilities
- CVE-2026-86472 fast-uri is a dependency-free RFC 3986 URI parser for Node.js, used by Fastify and ajv. CWE-178
- CVE-2026-87876 Two case-insensitive comparisons on request-derived usernames outside the main… CWE-178
- CVE-2026-84428 fastify versions before 5.12.2 implement the case-insensitive nature of HTTP header names… CWE-178
- CVE-2026-84303 gRPC-Go is the Go language implementation of gRPC. CWE-178
- CVE-2026-83612 xmldom is a pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and… CWE-178
- CVE-2026-73270 Improper Handling of Case Sensitivity vulnerability in Erlang/OTP inets httpd allows a… CWE-178
- CVE-2026-82726 Permissive Regular Expression vulnerability in ash-project ash_phoenix lets a remote… CWE-178
- CVE-2026-78959 Improper handling of case sensitivity in FileSystem in Google Chrome prior to… CWE-178