CVE-2026-44974 - @hapi/content parameter smuggling upload-filter bypass
@hapi/content before 6.0.2 parsed duplicate header parameters
inconsistently. Content.disposition() kept the last occurrence of a
parameter, while Content.type() kept the first occurrence for selected
parameters such as charset and boundary. That mismatch can become a
parameter-smuggling primitive when an upload filter, WAF, reverse proxy,
middleware, or downstream storage path resolves duplicate parameters
differently.
The most important production shape is upload filtering. If one component allows a request because it sees a safe filename or media boundary, while the component that writes or executes the upload sees the attacker-controlled duplicate, filename allowlists and content-type controls can be bypassed.
When to use it
Use this recipe when a Node.js repository, upload service, API gateway, or
storage pipeline depends on @hapi/content or parses multipart/header
parameters at a trust boundary. It supports source-code remediation, upload
filter bypass review, parser-consistency audit, and evidence that duplicate
Content-Disposition or Content-Type parameters cannot smuggle unsafe
filenames or metadata past controls.
Inputs
@hapi/contentversion, package lockfiles, upload routes, reverse proxies, WAF rules, storage key generation, and filename/content-type filters.- Source paths that parse
Content-Disposition,Content-Type, multipart boundaries, filenames, charsets, or downstream storage metadata. - Regression fixtures for duplicate parameters, mixed casing, quoted values, encoded filenames, benign uploads, and expected reject behavior.
- Boundary evidence showing every parser in the path sees the same filename, content type, boundary, and storage destination.
Affected versions
| Package | Vulnerable versions | Fixed versions |
|---|---|---|
@hapi/content |
< 6.0.2 |
6.0.2+ |
Indicator-of-exposure
- The repository resolves
@hapi/content <6.0.2directly or through Hapi upload, multipart, content negotiation, reverse-proxy, API gateway, or custom header parsing code. - Upload controls rely on
Content-Dispositionparameters such asfilename,name, orfilename*to enforce extension allowlists, storage paths, scan routing, tenant ownership, or executable-file denial. - Content routing, deserialization, parser choice, or sanitizer selection
relies on
Content-Typeparameters such ascharsetorboundary. - Multiple components parse the same header: WAF, proxy, framework middleware,
@hapi/content, multipart parser, object storage metadata, antivirus scanner, image processor, or downstream worker. - The application accepts direct-to-app uploads from untrusted users or imports uploads from email, webhooks, federation, partner APIs, support portals, CMS features, or agent/tool attachments.
Quick checks:
rg -n "@hapi/content|Content\\.disposition|Content\\.type|content-disposition|Content-Disposition|Content-Type|filename\\*?|boundary|multipart|form-data|multer|busboy|formidable|hapi|uploads?|allowlist|denylist" .
npm ls @hapi/content
pnpm why @hapi/content
yarn why @hapi/content
bun pm ls @hapi/content
Windows:
rg -n '@hapi/content|Content\.disposition|Content\.type|content-disposition|Content-Disposition|Content-Type|filename\*?|boundary|multipart|form-data|multer|busboy|formidable|hapi|uploads?|allowlist|denylist' .
npm ls @hapi/content
pnpm why @hapi/content
yarn why @hapi/content
bun pm ls @hapi/content
Do not upload executable test files to live services or send malformed headers through production WAFs during triage.
Remediation strategy
- Upgrade every controlled
@hapi/contentdependency, lockfile, workspace, generated dependency report, SBOM, Docker layer, CI image, and devcontainer to6.0.2+. - Add or verify request-boundary validation that rejects duplicate parameters
in
Content-DispositionandContent-Typebefore upload allowlists, storage-path decisions, parser selection, or worker routing consume them. - Normalize parser ownership. The same component should make the security decision and pass a canonicalized representation downstream, rather than letting a WAF, middleware, and worker each reinterpret raw header parameters.
- For upload filters, key decisions from server-generated metadata after parsing and validation. Do not trust client filenames for storage paths, executable-file denial, tenant routing, or scanner bypass decisions.
- Add regression tests for duplicate
filename,filename*,charset, andboundaryparameters that prove ambiguous requests are rejected, not silently accepted with first-wins or last-wins behavior. - If upgrade is blocked, contain by rejecting duplicate header parameters at the edge and disabling upload features where duplicate handling cannot be made unambiguous.
The prompt
Model context: this prompt was generated by GPT 5.5 Extra High reasoning.
You are remediating CVE-2026-44974 / GHSA-36hh-x5p5-jgc8, a high-severity
`@hapi/content` parameter-smuggling issue where duplicate `Content-Disposition`
or `Content-Type` parameters can be interpreted inconsistently and bypass
upload filters. Produce exactly one output:
- A reviewer-ready PR/change request that upgrades `@hapi/content`, refreshes
generated artifacts, rejects duplicate security-relevant header parameters at
upload and content-routing trust boundaries, adds safe regression tests, and
documents operator validation, or
- `TRIAGE.md` if this repository does not control an affected dependency,
upload parser, header parser, image/container, or deployable request path.
## Rules
- Scope only CVE-2026-44974 / GHSA-36hh-x5p5-jgc8 and directly related Hapi,
upload, multipart, header parsing, content-routing, WAF/proxy, and generated
dependency artifacts.
- Treat uploaded files, tenant IDs, filenames, object storage keys, scanner
output, customer content, support attachments, webhook payloads, and request
logs as sensitive.
- Do not upload executable files to live services, bypass production WAFs,
probe tenant uploads, print customer filenames, or run malformed-header tests
against production systems.
- Do not remove upload validation, antivirus scanning, content-type checks,
tenant isolation, or audit logging to make the advisory appear fixed.
- Do not auto-merge.
## Steps
1. Inventory every controlled `@hapi/content` consumer: package manifests,
lockfiles, workspaces, Hapi plugins, upload handlers, multipart parsers,
reverse-proxy adapters, API gateways, Dockerfiles, devcontainers, generated
dependency reports, SBOMs, and CI images.
2. Determine every resolved `@hapi/content` version. A target is vulnerable if
it resolves to `<6.0.2`.
3. Search for request paths that parse or trust `Content-Disposition` or
`Content-Type` parameters, especially `filename`, `filename*`, `name`,
`charset`, and `boundary`.
4. Map each upload or content-routing decision that depends on those
parameters: extension allowlists, executable-file denial, object storage
paths, tenant routing, scanner selection, image/document processing,
deserialization, webhook import, email attachment import, and agent/tool
attachment handling.
5. If the repository does not resolve an affected package and does not own a
relevant header-parsing or upload path, stop with `TRIAGE.md` listing
checked files, resolved versions, and any external platform owner.
6. Upgrade `@hapi/content` to `6.0.2+`. Keep Hapi framework packages,
multipart parsers, lockfiles, SBOMs, generated dependency reports, CI
images, and container layers consistent with the patched dependency graph.
7. Add or verify duplicate-parameter rejection before security decisions:
- reject duplicate `Content-Disposition` parameters;
- reject duplicate `Content-Type` parameters used for parser or sanitizer
selection;
- handle case-insensitive parameter names consistently;
- reject ambiguous encoded parameter names where framework APIs expose raw
headers;
- log only safe request metadata without customer filenames or file content.
8. Align parser ownership so the component that validates the header also
supplies canonical metadata to downstream workers. Avoid designs where a WAF
allows one interpretation and the application stores another.
9. Add safe regression tests using inert sample headers and temporary files:
- duplicate `filename` values are rejected;
- duplicate `filename*` and mixed `filename`/`filename*` policy is explicit;
- duplicate `charset` and `boundary` values are rejected when they influence
parser choice;
- upload allowlists do not depend on raw client filenames;
- logs and test output do not include customer content or secrets.
10. Add a PR body section named `CVE-2026-44974 operator actions` that states:
- `@hapi/content` versions before and after;
- which upload or header parsing paths were checked;
- which duplicate-parameter guards or tests were added;
- whether any WAF/proxy/parser disagreement remains and who owns it;
- whether caches, generated artifacts, images, or SBOMs were refreshed;
- which validation commands passed.
11. Run available validation: package install, lockfile integrity, upload
handler tests, header parser tests, lint/typecheck, unit tests, build,
dependency/security scans, SBOM refresh, image build, and CI workflow
validation.
12. Use PR title:
`fix(sec): remediate CVE-2026-44974 in @hapi/content uploads`.
## Stop conditions
- No affected `@hapi/content` package, upload parser, header parser, image, or
deployable request path is controlled by this repository.
- The affected runtime is supplied only by an external platform or reverse
proxy; document the owner, required fixed version, containment, and due date.
- Upload-parser changes require product ownership outside this PR; document the
owner, blast radius, temporary duplicate-parameter rejection, and follow-up.
- Verification would require sending malformed headers to production, probing
tenant uploads, uploading executable files, or exposing customer content.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.
Output contract
- A reviewer-ready PR or change request that upgrades
@hapi/content, rejects duplicate parameters at upload trust boundaries, aligns parser behavior, adds regression tests, and documents rollout controls. - Or a
TRIAGE.mdfile that lists inspected files, owner, observed version, upload boundary, parser mismatch, required fix, and residual risk. - The output must include exact validation commands and must not upload real customer files, bypass production filters, or expose storage credentials.
Verification - what the reviewer looks for
- No controlled package manifest, lockfile, SBOM, generated dependency report,
Docker layer, CI image, or devcontainer resolves
@hapi/content <6.0.2. - Upload and content-routing security decisions reject duplicate relevant header parameters instead of relying on first-wins or last-wins behavior.
- Tests cover duplicate
filename,filename*,charset, andboundarycases without live uploads or sensitive fixtures. - WAF, proxy, framework, parser, and downstream worker behavior are aligned or documented with an owner and containment.
- PR notes name refreshed artifacts and validation commands.
Watch for
- Updating only direct dependencies while Hapi plugins, framework packages, generated SBOMs, or container layers still resolve an older transitive copy.
- Upload extension allowlists that inspect one parsed filename while storage or processing code uses another.
- Case-sensitive duplicate checks that miss
Filenameversusfilename. - Allowing both
filenameandfilename*without an explicit conflict policy. - Treating this as a library-only bump while WAF, proxy, middleware, and worker parsers still disagree about duplicate header parameters.
- Regression tests that assert normal uploads still work but never cover ambiguous duplicate-parameter rejection.
Related recipes
- Source code injection sink audit
- Source code attack surface map
- Source code secrets and data exposure audit
- SAST finding triage and fix
References
- GitHub Advisory Database: https://github.com/advisories/GHSA-36hh-x5p5-jgc8
- Vendor advisory: https://github.com/hapijs/content/security/advisories/GHSA-36hh-x5p5-jgc8
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-44974
- Fix commit: https://github.com/hapijs/content/commit/3850079550c191d25e3643dc82a6d61144db8c2f