CWE-178
AllowedImproper Handling of Case Sensitivity
Abstraction: Base · Status: Incomplete
The product does not properly account for differences in case sensitivity when accessing or determining the properties of a resource, leading to inconsistent results.
196 vulnerabilities reference this CWE, most recent first.
GHSA-PXQG-8RWP-Q2X2
Vulnerability from github – Published: 2026-07-04 00:31 – Updated: 2026-07-04 00:31A security vulnerability has been detected in NousResearch hermes-agent up to 2026.4.30. Affected is the function GatewayStreamConsumer._filter_and_accumulate of the file gateway/stream_consumer.py of the component Streaming Reasoning Tag Filter. The manipulation leads to improper handling of case sensitivity. The attack may be initiated remotely. The attack's complexity is rated as high. The exploitability is told to be difficult. The exploit has been disclosed publicly and may be used. The project decided to not implement a dedicated fix: "[T]he analysis and the fix are both sound. It just lands below the bar for the maintenance cost of a duplicated scrub path."
{
"affected": [],
"aliases": [
"CVE-2026-14617"
],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-03T22:16:52Z",
"severity": "LOW"
},
"details": "A security vulnerability has been detected in NousResearch hermes-agent up to 2026.4.30. Affected is the function GatewayStreamConsumer._filter_and_accumulate of the file gateway/stream_consumer.py of the component Streaming Reasoning Tag Filter. The manipulation leads to improper handling of case sensitivity. The attack may be initiated remotely. The attack\u0027s complexity is rated as high. The exploitability is told to be difficult. The exploit has been disclosed publicly and may be used. The project decided to not implement a dedicated fix: \"[T]he analysis and the fix are both sound. It just lands below the bar for the maintenance cost of a duplicated scrub path.\"",
"id": "GHSA-pxqg-8rwp-q2x2",
"modified": "2026-07-04T00:31:23Z",
"published": "2026-07-04T00:31:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-14617"
},
{
"type": "WEB",
"url": "https://github.com/NousResearch/hermes-agent/issues/27288"
},
{
"type": "WEB",
"url": "https://github.com/NousResearch/hermes-agent/pull/28631#issuecomment-4622188016"
},
{
"type": "WEB",
"url": "https://gist.github.com/YLChen-007/2229e5505bcbb3e15a7ae8fba4c4be37"
},
{
"type": "WEB",
"url": "https://github.com/NousResearch/hermes-agent"
},
{
"type": "WEB",
"url": "https://vuldb.com/cve/CVE-2026-14617"
},
{
"type": "WEB",
"url": "https://vuldb.com/submit/844654"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/376134"
},
{
"type": "WEB",
"url": "https://vuldb.com/vuln/376134/cti"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P/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-Q534-42FM-GQR8
Vulnerability from github – Published: 2022-05-01 18:13 – Updated: 2024-02-08 03:32MyServer 0.8.9 and earlier does not properly handle uppercase characters in filename extensions, which allows remote attackers to obtain sensitive information (script source code) via a modified extension, as demonstrated by post.mscgI.
{
"affected": [],
"aliases": [
"CVE-2007-3365"
],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2007-06-22T18:30:00Z",
"severity": "HIGH"
},
"details": "MyServer 0.8.9 and earlier does not properly handle uppercase characters in filename extensions, which allows remote attackers to obtain sensitive information (script source code) via a modified extension, as demonstrated by post.mscgI.",
"id": "GHSA-q534-42fm-gqr8",
"modified": "2024-02-08T03:32:44Z",
"published": "2022-05-01T18:13:08Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2007-3365"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/34977"
},
{
"type": "WEB",
"url": "http://osvdb.org/37505"
},
{
"type": "WEB",
"url": "http://secunia.com/advisories/25754"
},
{
"type": "WEB",
"url": "http://securityreason.com/securityalert/2827"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/archive/1/471914/100/0/threaded"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/24571"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-Q8P7-6FHH-3H44
Vulnerability from github – Published: 2022-04-29 02:58 – Updated: 2025-04-03 04:02Apache for Apple Mac OS X 10.2.8 and 10.3.6 restricts access to files in a case sensitive manner, but the Apple HFS+ filesystem accesses files in a case insensitive manner, which allows remote attackers to read .DS_Store files and files beginning with ".ht" using alternate capitalization.
{
"affected": [],
"aliases": [
"CVE-2004-1083"
],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2004-12-03T05:00:00Z",
"severity": "MODERATE"
},
"details": "Apache for Apple Mac OS X 10.2.8 and 10.3.6 restricts access to files in a case sensitive manner, but the Apple HFS+ filesystem accesses files in a case insensitive manner, which allows remote attackers to read .DS_Store files and files beginning with \".ht\" using alternate capitalization.",
"id": "GHSA-q8p7-6fhh-3h44",
"modified": "2025-04-03T04:02:19Z",
"published": "2022-04-29T02:58:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2004-1083"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/18348"
},
{
"type": "WEB",
"url": "http://lists.apple.com/archives/security-announce/2004/Dec/msg00000.html"
},
{
"type": "WEB",
"url": "http://lists.apple.com/archives/security-announce/2005//Aug/msg00001.html"
},
{
"type": "WEB",
"url": "http://lists.apple.com/archives/security-announce/2005/Aug/msg00000.html"
},
{
"type": "WEB",
"url": "http://secunia.com/advisories/13362"
},
{
"type": "WEB",
"url": "http://www.ciac.org/ciac/bulletins/p-049.shtml"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/11802"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-Q9CM-88JX-3VFW
Vulnerability from github – Published: 2025-01-22 18:31 – Updated: 2025-03-19 15:19The Jenkins OpenId Connect Authentication Plugin 4.452.v2849b_d3945fa_ and earlier treats usernames as case-insensitive.
On a Jenkins instance configured with a case-sensitive OpenID Connect provider, this allows attackers to log in as any user by providing a username that differs only in letter case, potentially gaining administrator access to Jenkins.
OpenId Connect Authentication Plugin 4.453.v4d7765c854f4 introduces an advanced configuration option to manage username case sensitivity, with default to case-sensitive.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.jenkins-ci.plugins:oic-auth"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.453.v4d7765c854f4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-24399"
],
"database_specific": {
"cwe_ids": [
"CWE-178",
"CWE-276"
],
"github_reviewed": true,
"github_reviewed_at": "2025-01-22T19:23:59Z",
"nvd_published_at": "2025-01-22T17:15:13Z",
"severity": "HIGH"
},
"details": "The Jenkins OpenId Connect Authentication Plugin 4.452.v2849b_d3945fa_ and earlier treats usernames as case-insensitive.\n\nOn a Jenkins instance configured with a case-sensitive OpenID Connect provider, this allows attackers to log in as any user by providing a username that differs only in letter case, potentially gaining administrator access to Jenkins.\n\nOpenId Connect Authentication Plugin 4.453.v4d7765c854f4 introduces an advanced configuration option to manage username case sensitivity, with default to case-sensitive.",
"id": "GHSA-q9cm-88jx-3vfw",
"modified": "2025-03-19T15:19:39Z",
"published": "2025-01-22T18:31:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-24399"
},
{
"type": "WEB",
"url": "https://github.com/jenkinsci/oic-auth-plugin/commit/4d7765c854f4f5e6e3c26ed950a26042a7527875"
},
{
"type": "PACKAGE",
"url": "https://github.com/jenkinsci/oic-auth-plugin"
},
{
"type": "WEB",
"url": "https://www.jenkins.io/security/advisory/2025-01-22/#SECURITY-3461"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Improper handling of case sensitivity in Jenkins OpenId Connect Authentication Plugin "
}
GHSA-QC2Q-P7WX-3PX3
Vulnerability from github – Published: 2026-09-08 20:50 – Updated: 2026-09-08 20:50Summary
A vulnerability in the xDS RBAC HTTP filter implementation in grpc-go allows remote attackers to bypass authorization policies (specifically DENY rules) by using mixed-case or canonical-case header matchers (e.g., X-Role instead of x-role). Additionally, the safety guards introduced by gRFC A41 to block grpc- prefixed headers can be evaded via variations in casing (e.g., Grpc-Status).
Impact
When an operator defines an RBAC policy referencing headers containing uppercase letters (e.g. X-Role), grpc-go fails to match incoming metadata keys because they are unconditionally lowercased. Because of this case-sensitivity mismatch, a policy designed to block requests containing specific header values fails open: the rule is evaluated as a non-match, and traffic that should have been rejected is served.
Furthermore, gRFC A41 requires rejecting configuration schemas specifying header matchers starting with grpc-. Because this check is executed case-sensitively in grpc-go, attackers can bypass the validation by specifying titles like Grpc-Status.
Patches
The problem is fixed in master and in the 1.83.1 release.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.83.0"
},
"package": {
"ecosystem": "Go",
"name": "google.golang.org/grpc"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.83.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-84303"
],
"database_specific": {
"cwe_ids": [
"CWE-178",
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-08T20:50:21Z",
"nvd_published_at": "2026-09-01T19:17:30Z",
"severity": "MODERATE"
},
"details": "### Summary\nA vulnerability in the xDS RBAC HTTP filter implementation in grpc-go allows remote attackers to bypass authorization policies (specifically DENY rules) by using mixed-case or canonical-case header matchers (e.g., X-Role instead of x-role). Additionally, the safety guards introduced by gRFC A41 to block grpc- prefixed headers can be evaded via variations in casing (e.g., Grpc-Status).\n\n### Impact\nWhen an operator defines an RBAC policy referencing headers containing uppercase letters (e.g. X-Role), grpc-go fails to match incoming metadata keys because they are unconditionally lowercased. Because of this case-sensitivity mismatch, a policy designed to block requests containing specific header values fails open: the rule is evaluated as a non-match, and traffic that should have been rejected is served.\n\nFurthermore, gRFC A41 requires rejecting configuration schemas specifying header matchers starting with grpc-. Because this check is executed case-sensitively in grpc-go, attackers can bypass the validation by specifying titles like Grpc-Status.\n\n### Patches\nThe problem is fixed in `master` and in the 1.83.1 release.",
"id": "GHSA-qc2q-p7wx-3px3",
"modified": "2026-09-08T20:50:21Z",
"published": "2026-09-08T20:50:21Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/security/advisories/GHSA-qc2q-p7wx-3px3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-84303"
},
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/pull/9332"
},
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/pull/9335"
},
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/commit/db9482836c298f234c896cf82ab68cafc78237f8"
},
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/commit/ebba6f3f1b206e2b4dc4d1d5a96d18430302c2fe"
},
{
"type": "PACKAGE",
"url": "https://github.com/grpc/grpc-go"
},
{
"type": "WEB",
"url": "https://github.com/grpc/grpc-go/releases/tag/v1.83.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "gRPC-Go: xDS RBAC HTTP Filter bypass via mixed-case Header Matching and gRFC A41 validation evasion"
}
GHSA-QC48-8MCW-GXQV
Vulnerability from github – Published: 2022-04-30 18:13 – Updated: 2024-01-26 18:30The default configuration of BEA WebLogic 3.1.8 through 4.5.1 allows a remote attacker to view source code of a JSP program by requesting a URL which provides the JSP extension in upper case.
{
"affected": [],
"aliases": [
"CVE-2000-0499"
],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2000-06-08T04:00:00Z",
"severity": "MODERATE"
},
"details": "The default configuration of BEA WebLogic 3.1.8 through 4.5.1 allows a remote attacker to view source code of a JSP program by requesting a URL which provides the JSP extension in upper case.",
"id": "GHSA-qc48-8mcw-gxqv",
"modified": "2024-01-26T18:30:28Z",
"published": "2022-04-30T18:13:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2000-0499"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/4694"
},
{
"type": "WEB",
"url": "http://archives.neohapsis.com/archives/ntbugtraq/2000-q2/0262.htm"
},
{
"type": "WEB",
"url": "http://developer.bea.com/alerts/security_000612.html"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/1328"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-QCC2-C9CP-C24W
Vulnerability from github – Published: 2023-04-20 15:30 – Updated: 2024-04-04 03:36An issue was discovered in ONOS 2.5.1. An intent with an uppercase letter in a device ID shows the CORRUPT state, which is misleading to a network operator. Improper handling of case sensitivity causes inconsistency between intent and flow rules in the network.
{
"affected": [],
"aliases": [
"CVE-2022-29604"
],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-04-20T13:15:07Z",
"severity": "CRITICAL"
},
"details": "An issue was discovered in ONOS 2.5.1. An intent with an uppercase letter in a device ID shows the CORRUPT state, which is misleading to a network operator. Improper handling of case sensitivity causes inconsistency between intent and flow rules in the network.",
"id": "GHSA-qcc2-c9cp-c24w",
"modified": "2024-04-04T03:36:47Z",
"published": "2023-04-20T15:30:26Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-29604"
},
{
"type": "WEB",
"url": "https://wiki.onosproject.org/display/ONOS/Intent+Framework"
},
{
"type": "WEB",
"url": "https://www.usenix.org/system/files/sec23fall-prepub-285_kim-jiwon.pdf"
}
],
"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:H",
"type": "CVSS_V3"
}
]
}
GHSA-QCXP-GM7M-4J5V
Vulnerability from github – Published: 2026-07-29 15:40 – Updated: 2026-07-30 12:32Quarkus HTTP path-based authorization policies can be bypassed using encoded semicolons (%3B) to smuggle matrix parameters past the security layer, and using encoded slashes (%2F) or backslashes (%5C) to access protected static resources. This is a distinct issue from CVE-2026-39852, which addressed only literal semicolon stripping.
### Technical Details
The security layer (AbstractPathMatchingHttpSecurityPolicy) normalizes request paths using Vert.x's normalizedPath(), which only decodes unreserved RFC 3986 characters (letters, digits, -, ., _, ~). It then strips matrix parameters by looking for literal ; characters. This creates two mismatches:
- Encoded semicolons (
%3B): Since%3Bis not decoded by normalizedPath(), the matrix parameter stripping in pathWithoutMatrixParams() never sees it. The encoded semicolon and everything after it become part of the path segment, causing policy matching to fail. This affects all path-policy-protected endpoints. - Static resource path mismatch: Static resource handlers (StaticHandlerImpl, FileSystemStaticHandler) perform full
percent-decoding via URIDecoder.decodeURIComponent() and backslash-to-slash conversion before filesystem resolution.
Reserved characters like
%2F(slash) and%5C(backslash) that survive the security layer's partial decoding are fully decoded before file serving.
REST endpoints using Quarkus REST (RESTEasy Reactive) are not affected by the %2F/%5C vectors because the routing layer also uses normalizedPath() — both security and routing agree on the path, so no mismatch exists.
Attack Vectors
Encoded semicolon (matrix parameter smuggling), affects all path-policy-protected endpoints:
/api/admin%3Bbypass=true/data: security sees this as a single segmentadmin%3Bbypass=true, which does not match the/api/admin/* policy. The request passes through unauthenticated./api/secret%3b/data: same mechanism with lowercase hex digit.
Encoded slash/backslash on static resources, affects static files behind path policies:
- /static-secret%2Fhtml, security does not match /static-secret.html policy; static handler decodes %2F to / and may
resolve the file.
- /static-secret%5Chtml. static handler decodes %5C to \, then converts to /.
Double encoding, affects static resources:
- /secret%252Fconfidential.html, first decode by normalizedPath() turns %25 into %, producing %2F. Static handler's
second decode turns %2F into /.
The following vectors were investigated and confirmed not exploitable:
- Unreserved character encoding (
/api/adm%69n/data):normalizedPath()decodes these. Both security and routing see/api/admin/data. - Null byte injection (
/api/admin%00/data):%00is not decoded bynormalizedPath(). - Encoded dot segments (
/api/%2e%2e/secret/data): Period is unreserved, so%2eis decoded to.bynormalizedPath(), thenremoveDots()normalizes..segments. - REST endpoint bypass via
%2F/%5C: Routing uses the samenormalizedPath()as security. The encoded slash/backslash doesn't match any route.
Root Cause
pathWithoutMatrixParams() operates on the partially-decoded output of normalizedPath(), where reserved characters
remain encoded. It searches for literal ; but never sees %3B. The fix (normalizePath()) performs full percent-decoding
in a loop before stripping matrix parameters, removing null bytes, normalizing backslashes, and resolving dot
segments, aligning the security layer's view of the path with what downstream handlers resolve.
Impact
- Unauthenticated access to endpoints protected by
quarkus.http.auth.permissionpath-based policies via%3Bsmuggling - Static resource exposure by bypassing path policies on protected files via
%2F/%5C - Applications using annotation-based security (
@RolesAllowed,@Authenticated) on JAX-RS resources without path-based policies are not affected by the%2F/%5Cvectors, but may still be affected by%3Bif path policies coexist
Proof of Concept
# Encoded semicolon bypass — works on any path-policy-protected endpoint
# Security sees "/api/admin%3Bbypass=true/data", doesn't match /api/admin/* policy
curl -v http://target/api/admin%3Bbypass=true/data
# Encoded semicolon on authenticated endpoint
curl -v http://target/api/secret%3b/data
# Static resource bypass via encoded slash (if static file behind path policy)
curl -v http://target/static-secret%2Fhtml
# Static resource bypass via encoded backslash
curl -v http://target/static-secret%5Chtml
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "io.quarkus:quarkus-vertx-http"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.20.6.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "io.quarkus:quarkus-vertx-http"
},
"ranges": [
{
"events": [
{
"introduced": "3.21.0.CR1"
},
{
"fixed": "3.27.4.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "io.quarkus:quarkus-vertx-http"
},
"ranges": [
{
"events": [
{
"introduced": "3.28.0.CR1"
},
{
"fixed": "3.33.2.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "io.quarkus:quarkus-vertx-http"
},
"ranges": [
{
"events": [
{
"introduced": "3.34.0.CR1"
},
{
"fixed": "3.36.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Maven",
"name": "io.quarkus:quarkus-vertx-http"
},
"ranges": [
{
"events": [
{
"introduced": "3.37.0.CR1"
},
{
"fixed": "3.37.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-50559"
],
"database_specific": {
"cwe_ids": [
"CWE-178",
"CWE-287",
"CWE-41",
"CWE-551",
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-29T15:40:05Z",
"nvd_published_at": "2026-06-19T21:17:02Z",
"severity": "HIGH"
},
"details": "Quarkus HTTP path-based authorization policies can be bypassed using encoded semicolons (%3B) to smuggle matrix\n parameters past the security layer, and using encoded slashes (%2F) or backslashes (%5C) to access protected static\n resources. This is a distinct issue from CVE-2026-39852, which addressed only literal semicolon stripping.\n\n ### Technical Details\n\n The security layer (AbstractPathMatchingHttpSecurityPolicy) normalizes request paths using Vert.x\u0027s normalizedPath(),\n which only decodes unreserved RFC 3986 characters (letters, digits, -, ., _, ~). It then strips matrix parameters by\n looking for literal ; characters. This creates two mismatches:\n\n 1. Encoded semicolons (`%3B`): Since `%3B` is not decoded by normalizedPath(), the matrix parameter stripping in\n pathWithoutMatrixParams() never sees it. The encoded semicolon and everything after it become part of the path\n segment, causing policy matching to fail. This affects all path-policy-protected endpoints.\n 2. Static resource path mismatch: Static resource handlers (StaticHandlerImpl, FileSystemStaticHandler) perform full\n percent-decoding via URIDecoder.decodeURIComponent() and backslash-to-slash conversion before filesystem resolution.\n Reserved characters like `%2F` (slash) and `%5C` (backslash) that survive the security layer\u0027s partial decoding are fully\n decoded before file serving.\n\n REST endpoints using Quarkus REST (RESTEasy Reactive) are not affected by the `%2F/%5C` vectors because the routing layer also uses `normalizedPath()` \u2014 both security and routing agree on the path, so no mismatch exists.\n\n### Attack Vectors\n\n Encoded semicolon (matrix parameter smuggling), affects all path-policy-protected endpoints:\n \n - `/api/admin%3Bbypass=true/data`: security sees this as a single segment `admin%3Bbypass=true`, which does not match the\n `/api/admin/* policy`. The request passes through unauthenticated.\n - `/api/secret%3b/data`: same mechanism with lowercase hex digit.\n\n Encoded slash/backslash on static resources, affects static files behind path policies:\n - `/static-secret%2Fhtml`, security does not match /static-secret.html policy; static handler decodes `%2F` to `/` and may\n resolve the file.\n - `/static-secret%5Chtml `. static handler decodes `%5C` to `\\`, then converts to `/`.\n\n Double encoding, affects static resources:\n - `/secret%252Fconfidential.html`, first decode by normalizedPath() turns `%25` into `%`, producing `%2F`. Static handler\u0027s\n second decode turns `%2F` into `/`.\n\n The following vectors were investigated and confirmed not exploitable:\n\n - Unreserved character encoding (`/api/adm%69n/data`): `normalizedPath()` decodes these. Both security and routing see\n `/api/admin/data`. \n - Null byte injection (`/api/admin%00/data`): `%00` is not decoded by `normalizedPath()`. \n - Encoded dot segments (`/api/%2e%2e/secret/data`): Period is unreserved, so `%2e` is decoded to `.` by `normalizedPath()`,\n then `removeDots()` normalizes `..` segments. \n - REST endpoint bypass via `%2F/%5C`: Routing uses the same `normalizedPath()` as security. The encoded slash/backslash\n doesn\u0027t match any route. \n\n### Root Cause\n\n `pathWithoutMatrixParams()` operates on the partially-decoded output of `normalizedPath()`, where reserved characters\n remain encoded. It searches for literal ; but never sees `%3B.` The fix (`normalizePath()`) performs full percent-decoding\n in a loop before stripping matrix parameters, removing null bytes, normalizing backslashes, and resolving dot\n segments, aligning the security layer\u0027s view of the path with what downstream handlers resolve.\n\n### Impact\n\n - Unauthenticated access to endpoints protected by `quarkus.http.auth.permission` path-based policies via `%3B` smuggling\n - Static resource exposure by bypassing path policies on protected files via `%2F/%5C`\n - Applications using annotation-based security (`@RolesAllowed`, `@Authenticated`) on JAX-RS resources without path-based\n policies are not affected by the `%2F/%5C` vectors, but may still be affected by `%3B` if path policies coexist\n\n### Proof of Concept\n\n```\n # Encoded semicolon bypass \u2014 works on any path-policy-protected endpoint\n # Security sees \"/api/admin%3Bbypass=true/data\", doesn\u0027t match /api/admin/* policy\n curl -v http://target/api/admin%3Bbypass=true/data\n\n # Encoded semicolon on authenticated endpoint\n curl -v http://target/api/secret%3b/data\n\n # Static resource bypass via encoded slash (if static file behind path policy)\n curl -v http://target/static-secret%2Fhtml\n\n # Static resource bypass via encoded backslash\n curl -v http://target/static-secret%5Chtml\n```",
"id": "GHSA-qcxp-gm7m-4j5v",
"modified": "2026-07-30T12:32:16Z",
"published": "2026-07-29T15:40:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/quarkusio/quarkus/security/advisories/GHSA-qcxp-gm7m-4j5v"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-50559"
},
{
"type": "WEB",
"url": "https://github.com/quarkusio/quarkus/commit/919b80017d85564143a845b38e9cca54aff5b3cc"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26017"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26018"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26194"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26586"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34608"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:36820"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:48151"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-50559"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2486959"
},
{
"type": "PACKAGE",
"url": "https://github.com/quarkusio/quarkus"
},
{
"type": "WEB",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-50559.json"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Quarkus: Authentication/Authorization Bypass via Advanced Path Normalization Vulnerabilities"
}
GHSA-QMWH-9M9C-H36M
Vulnerability from github – Published: 2026-04-07 18:16 – Updated: 2026-04-07 18:16Summary
The fix for ExifTool arbitrary file write (commit 043b158, released in v8.29.0) uses a case-sensitive blocklist to filter dangerous pseudo-tags. ExifTool processes tag names case-insensitively, so alternate casings bypass the filter. The blocklist also omits the HardLink and SymLink pseudo-tags entirely.
Confirmed end-to-end against Gotenberg v8.29.1 via the unauthenticated HTTP API.
Root Cause
pkg/modules/exiftool/exiftool.go lines 231-237:
dangerousTags := []string{
"FileName", // Writing this triggers a file rename in ExifTool
"Directory", // Writing this triggers a file move in ExifTool
}
for _, tag := range dangerousTags {
delete(metadata, tag)
}
Go's delete(metadata, tag) is case-sensitive. It only removes the exact keys "FileName" and "Directory". ExifTool processes tag names case-insensitively (per ExifTool documentation). Alternate casings like filename, FILENAME, directory all bypass the Go blocklist but ExifTool treats them identically.
The go-exiftool library passes tag names directly to ExifTool's stdin at line 258:
fmt.Fprintln(e.stdin, "-"+k+"="+str)
So filename becomes -filename=/attacker/path which ExifTool interprets as -FileName=/attacker/path.
The blocklist also omits two dangerous ExifTool pseudo-tags:
- HardLink: creates a hard link to the file at the specified path
- SymLink: creates a symbolic link to the file at the specified path
PoC
All three vectors confirmed against a running Gotenberg v8.29.1 Docker container.
Case-insensitive filename bypass (file moved to /tmp/evil_bypass.pdf):
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
-F files=@sample.pdf \
-F 'metadata={"filename": "/tmp/evil_bypass.pdf"}'
HardLink (hard link created at /tmp/hardlink_bypass.pdf):
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
-F files=@sample.pdf \
-F 'metadata={"HardLink": "/tmp/hardlink_bypass.pdf"}'
SymLink (symbolic link created at /tmp/symlink_bypass.pdf):
curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \
-F files=@sample.pdf \
-F 'metadata={"SymLink": "/tmp/symlink_bypass.pdf"}'
Verification inside the container:
$ docker exec gotenberg-poc ls -la /tmp/evil_bypass.pdf /tmp/hardlink_bypass.pdf /tmp/symlink_bypass.pdf
-rw-r--r-- 1 gotenberg gotenberg 321 ... /tmp/evil_bypass.pdf
-rw-r--r-- 1 gotenberg gotenberg 321 ... /tmp/hardlink_bypass.pdf
lrwxrwxrwx 1 gotenberg gotenberg 119 ... /tmp/symlink_bypass.pdf -> /tmp/.../source.pdf
Also confirmed ExifTool case-insensitivity directly:
exiftool -filename=bypassed.pdf test.pdf # Works identically to -FileName=
Impact
An attacker with access to the Gotenberg API (unauthenticated by default) can:
- Rename/move uploaded PDFs to arbitrary filesystem paths via lowercase
filename/directory - Create hard links at arbitrary paths via
HardLink, persisting data beyond temp directory cleanup - Create symbolic links at arbitrary paths via
SymLink
In containerized deployments, impact is limited to the container filesystem (DoS by overwriting temp files). In bare-metal deployments or those with shared volumes, this can affect other services.
Suggested Fix
Use case-insensitive comparison and expand the blocklist:
dangerousTags := []string{
"FileName",
"Directory",
"HardLink",
"SymLink",
}
for key := range metadata {
for _, tag := range dangerousTags {
if strings.EqualFold(key, tag) {
delete(metadata, key)
}
}
}
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 8.29.1"
},
"package": {
"ecosystem": "Go",
"name": "github.com/gotenberg/gotenberg/v8"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "8.30.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-178",
"CWE-73"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-07T18:16:22Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nThe fix for ExifTool arbitrary file write (commit `043b158`, released in v8.29.0) uses a case-sensitive blocklist to filter dangerous pseudo-tags. ExifTool processes tag names case-insensitively, so alternate casings bypass the filter. The blocklist also omits the `HardLink` and `SymLink` pseudo-tags entirely.\n\nConfirmed end-to-end against Gotenberg v8.29.1 via the unauthenticated HTTP API.\n\n## Root Cause\n\n`pkg/modules/exiftool/exiftool.go` lines 231-237:\n\n dangerousTags := []string{\n \"FileName\", // Writing this triggers a file rename in ExifTool\n \"Directory\", // Writing this triggers a file move in ExifTool\n }\n for _, tag := range dangerousTags {\n delete(metadata, tag)\n }\n\nGo\u0027s `delete(metadata, tag)` is case-sensitive. It only removes the exact keys `\"FileName\"` and `\"Directory\"`. ExifTool processes tag names case-insensitively (per ExifTool documentation). Alternate casings like `filename`, `FILENAME`, `directory` all bypass the Go blocklist but ExifTool treats them identically.\n\nThe go-exiftool library passes tag names directly to ExifTool\u0027s stdin at line 258:\n\n fmt.Fprintln(e.stdin, \"-\"+k+\"=\"+str)\n\nSo `filename` becomes `-filename=/attacker/path` which ExifTool interprets as `-FileName=/attacker/path`.\n\nThe blocklist also omits two dangerous ExifTool pseudo-tags:\n- `HardLink`: creates a hard link to the file at the specified path\n- `SymLink`: creates a symbolic link to the file at the specified path\n\n## PoC\n\nAll three vectors confirmed against a running Gotenberg v8.29.1 Docker container.\n\n**Case-insensitive filename bypass (file moved to /tmp/evil_bypass.pdf):**\n\n curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \\\n -F files=@sample.pdf \\\n -F \u0027metadata={\"filename\": \"/tmp/evil_bypass.pdf\"}\u0027\n\n**HardLink (hard link created at /tmp/hardlink_bypass.pdf):**\n\n curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \\\n -F files=@sample.pdf \\\n -F \u0027metadata={\"HardLink\": \"/tmp/hardlink_bypass.pdf\"}\u0027\n\n**SymLink (symbolic link created at /tmp/symlink_bypass.pdf):**\n\n curl -X POST http://localhost:3000/forms/pdfengines/metadata/write \\\n -F files=@sample.pdf \\\n -F \u0027metadata={\"SymLink\": \"/tmp/symlink_bypass.pdf\"}\u0027\n\nVerification inside the container:\n\n $ docker exec gotenberg-poc ls -la /tmp/evil_bypass.pdf /tmp/hardlink_bypass.pdf /tmp/symlink_bypass.pdf\n -rw-r--r-- 1 gotenberg gotenberg 321 ... /tmp/evil_bypass.pdf\n -rw-r--r-- 1 gotenberg gotenberg 321 ... /tmp/hardlink_bypass.pdf\n lrwxrwxrwx 1 gotenberg gotenberg 119 ... /tmp/symlink_bypass.pdf -\u003e /tmp/.../source.pdf\n\nAlso confirmed ExifTool case-insensitivity directly:\n\n exiftool -filename=bypassed.pdf test.pdf # Works identically to -FileName=\n\n## Impact\n\nAn attacker with access to the Gotenberg API (unauthenticated by default) can:\n\n1. Rename/move uploaded PDFs to arbitrary filesystem paths via lowercase `filename`/`directory`\n2. Create hard links at arbitrary paths via `HardLink`, persisting data beyond temp directory cleanup\n3. Create symbolic links at arbitrary paths via `SymLink`\n\nIn containerized deployments, impact is limited to the container filesystem (DoS by overwriting temp files). In bare-metal deployments or those with shared volumes, this can affect other services.\n\n## Suggested Fix\n\nUse case-insensitive comparison and expand the blocklist:\n\n dangerousTags := []string{\n \"FileName\",\n \"Directory\",\n \"HardLink\",\n \"SymLink\",\n }\n for key := range metadata {\n for _, tag := range dangerousTags {\n if strings.EqualFold(key, tag) {\n delete(metadata, key)\n }\n }\n }",
"id": "GHSA-qmwh-9m9c-h36m",
"modified": "2026-04-07T18:16:22Z",
"published": "2026-04-07T18:16:22Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gotenberg/gotenberg/security/advisories/GHSA-qmwh-9m9c-h36m"
},
{
"type": "WEB",
"url": "https://github.com/gotenberg/gotenberg/commit/15050a311b73d76d8b9223bafe7fa7ba71240011"
},
{
"type": "PACKAGE",
"url": "https://github.com/gotenberg/gotenberg"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Gotenberg has incomplete fix for ExifTool arbitrary file write: case-insensitive bypass and missing HardLink/SymLink tags"
}
GHSA-QP9X-WP8F-QGJJ
Vulnerability from github – Published: 2026-05-28 22:46 – Updated: 2026-05-28 22:46DelegatedRole._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.
Vulnerable code
tuf/api/_payload.py (HEAD 7ecb67d):
1183 @staticmethod
1184 def _is_target_in_pathpattern(targetpath: str, pathpattern: str) -> bool:
1185 """Determine whether ``targetpath`` matches the ``pathpattern``."""
1186 # We need to make sure that targetpath and pathpattern are pointing to
1187 # the same directory as fnmatch doesn't threat "/" as a special symbol.
1188 target_parts = targetpath.split("/")
1189 pattern_parts = pathpattern.split("/")
1190 if len(target_parts) != len(pattern_parts):
1191 return False
1192
1193 # Every part in the pathpattern could include a glob pattern, that's why
1194 # each of the target and pathpattern parts should match.
1195 for target, pattern in zip(target_parts, pattern_parts, strict=True):
1196 if not fnmatch.fnmatch(target, pattern):
1197 return False
1198 return True
fnmatch.fnmatch source (Python 3.12, unchanged in current mainline):
def fnmatch(name, pat):
...
name = os.path.normcase(name)
pat = os.path.normcase(pat)
return fnmatchcase(name, pat)
Fix
Replace fnmatch.fnmatch with fnmatch.fnmatchcase, which is explicitly documented as "not applying case normalization", so it behaves identically across platforms.
Attack
- A TUF repository with two path-based delegations whose patterns differ only in case — for example,
Foo/*andfoo/*. - The "attacker" delegation is listed BEFORE the "legit" delegation in the delegation order.
- The client searches for
foo/something: on Windows, it will find the "attacker" provided target "Foo/something".
Exploitability caveats
- The attack needs a repository configuration with case-colliding delegation path patterns. The attacker must control one of the delegated roles.
- Delegation ordering matters: the attacker-controlled role must be visited BEFORE the legit role in the pre-order walk.
- The client must run on Windows. No effect on Linux/macOS.
Credit
Reporter: Koda Reef @kodareef5 Advisory edits: Jussi Kukkonen @jku
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 6.0.0"
},
"package": {
"ecosystem": "PyPI",
"name": "tuf"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.0.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-178"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-28T22:46:13Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "`DelegatedRole._is_target_in_pathpattern` uses `fnmatch.fnmatch` to decide whether a given target path is authorized by a delegation\u0027s glob pattern.\n\nPython\u0027s `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 `\\`.\n\nAs a result, python-tuf\u0027s 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.\n\nThe result on Windows is a TUF specification violation in the python-tuf `ngclient` implementation.\n\n## Vulnerable code\n\n`tuf/api/_payload.py` (HEAD `7ecb67d`):\n\n```python\n1183 @staticmethod\n1184 def _is_target_in_pathpattern(targetpath: str, pathpattern: str) -\u003e bool:\n1185 \"\"\"Determine whether ``targetpath`` matches the ``pathpattern``.\"\"\"\n1186 # We need to make sure that targetpath and pathpattern are pointing to\n1187 # the same directory as fnmatch doesn\u0027t threat \"/\" as a special symbol.\n1188 target_parts = targetpath.split(\"/\")\n1189 pattern_parts = pathpattern.split(\"/\")\n1190 if len(target_parts) != len(pattern_parts):\n1191 return False\n1192\n1193 # Every part in the pathpattern could include a glob pattern, that\u0027s why\n1194 # each of the target and pathpattern parts should match.\n1195 for target, pattern in zip(target_parts, pattern_parts, strict=True):\n1196 if not fnmatch.fnmatch(target, pattern):\n1197 return False\n1198 return True\n```\n\n`fnmatch.fnmatch` source (Python 3.12, unchanged in current mainline):\n\n```python\ndef fnmatch(name, pat):\n ...\n name = os.path.normcase(name)\n pat = os.path.normcase(pat)\n return fnmatchcase(name, pat)\n```\n\n## Fix\n\nReplace `fnmatch.fnmatch` with `fnmatch.fnmatchcase`, which is explicitly documented as \"not applying case normalization\", so it behaves identically across platforms.\n\n## Attack\n\n1. A TUF repository with two path-based delegations whose patterns differ only in case \u2014 for example, `Foo/*` and `foo/*`.\n2. The \"attacker\" delegation is listed BEFORE the \"legit\" delegation in the delegation order.\n3. The client searches for `foo/something`: on Windows, it will find the \"attacker\" provided target \"Foo/something\".\n\n\n## Exploitability caveats \n\n* The attack needs a repository configuration with case-colliding delegation path patterns. The attacker must control one of the delegated roles.\n* Delegation ordering matters: the attacker-controlled role must be visited BEFORE the legit role in the pre-order walk.\n* The client must run on Windows. No effect on Linux/macOS.\n\n## Credit\n\nReporter: Koda Reef @kodareef5 \nAdvisory edits: Jussi Kukkonen @jku",
"id": "GHSA-qp9x-wp8f-qgjj",
"modified": "2026-05-28T22:46:13Z",
"published": "2026-05-28T22:46:13Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/theupdateframework/python-tuf/security/advisories/GHSA-qp9x-wp8f-qgjj"
},
{
"type": "PACKAGE",
"url": "https://github.com/theupdateframework/python-tuf"
},
{
"type": "WEB",
"url": "https://github.com/theupdateframework/python-tuf/releases/tag/v7.0.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "tuf has platform-dependent delegation path matching"
}
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.
No CAPEC attack patterns related to this CWE.