← Back to Feed CACHED · 2026-09-04 11:00:14 · CACHE_KEY CVE-2026-84428
CVE-2026-84428 · CWE-178 · Disclosed 2026-09-04

Fastify Header Validation Bypass via Incomplete Schema Case Normalization

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

A lock that only checks your ID badge if you hold it right-side up

CVE-2026-84428 is a validation bypass in Fastify versions prior to 5.12.2 (also fixed in 6.0.0). The framework lowercases incoming HTTP header property names during schema compilation—mirroring Node.js’s own behavior—but this normalization was incomplete: it only applied to top-level properties keys and root required arrays. The JSON Schema Draft 7 dependencies keyword and nested subschema property names were left unnormalized. An attacker can therefore bypass cross-header dependency checks (e.g., a schema requiring X-Admin-Token when X-Admin is present) by simply sending the trigger header while omitting the dependent one. The schema match silently fails, and the request sails through without validation.

The vendor rates this HIGH at CVSS 7.5, which reflects the network-accessible, unauthenticated, low-complexity attack surface. On paper that’s alarming. In practice, the severity is overstated for most Fastify deployments. The bug only fires when developers use the dependencies keyword inside header schemas with mixed-case property names in nested subschemas—a pattern that is rare even among teams doing rigorous schema validation. Most Fastify apps rely on body validation or simple required-header checks, not cross-header dependency graphs. The impact is also capped at integrity (C:N/I:H/A:N): you bypass a validation gate, not gain code execution. The real risk depends entirely on what the validated endpoint does when bad input gets through.

"Header schema bypass needs a rare coding pattern most Fastify apps never use"
02 · The Attack Path

3 steps from start to impact.

STEP 01

Identify a Fastify endpoint using header schema dependencies

The attacker probes for endpoints that return 400-class errors indicating missing required headers. They look for responses that mention specific header names or validation keywords, indicating the application uses JSON Schema’s dependencies construct to enforce cross-header requirements. This requires the target application to use this relatively uncommon pattern.
Conditions required:
  • Target runs Fastify < 5.12.2
  • Application uses dependencies keyword in header schema with mixed-case property names
Where this breaks in practice:
  • Most Fastify apps do not use header schema dependencies at all
  • Even fewer use mixed-case property names inside nested subschemas rather than lowercase
STEP 02

Craft request with trigger header, omit dependent header

The attacker sends the trigger header (e.g., x-admin: true) without the dependent header (x-admin-token). Because Fastify’s lowercased incoming headers don’t match the unnormalized mixed-case X-Admin-Token key in the dependencies subschema, the dependency check never fires. The request passes schema validation and reaches the route handler.
Conditions required:
  • Knowledge of the header dependency structure from step 1
Where this breaks in practice:
  • Attacker must guess or enumerate the specific header names and dependency structure
  • No public tooling automates this pattern
Detection/coverage: WAFs with custom rules matching requests missing expected authorization-adjacent headers can flag anomalies
STEP 03

Exploit the unvalidated endpoint

With validation bypassed, the attacker’s request reaches the route handler with missing or malformed headers that the developer assumed would always be present. The actual impact depends entirely on what the handler does: it could be a no-op, or it could grant elevated access, skip authorization checks, or process unvalidated data. This is an application-specific secondary exploit, not a guaranteed outcome of the CVE itself.
Conditions required:
  • The route handler relies on schema validation as its sole authorization or input-validation gate
  • The handler performs a security-sensitive action when the dependent header is absent
Where this breaks in practice:
  • Well-architected apps enforce authorization in middleware hooks (onRequest, preValidation), not solely through schema validation
  • Defense-in-depth means the handler typically has its own checks
Detection/coverage: Application-layer logging of authorization decisions; APM/tracing tools flagging requests that bypass expected validation paths
03 · Compensating Control

1
Move cross-header authorization logic into onRequest or preValidation hooks — Schema validation was never designed to be a security enforcement boundary. Move any authorization checks (e.g., require token when admin header is present) into Fastify lifecycle hooks that execute before the handler. This eliminates the vulnerability’s impact regardless of patch status. No mitigation SLA applies for MEDIUM—go straight to the 365-day remediation window.
2
Lowercase all property names in header schemas immediately — Audit your route schemas for any dependencies, if/then/else, or allOf/anyOf/oneOf blocks under schema.headers that use mixed-case property names. Convert them to lowercase to match Node.js’s header normalization. This is a code-level workaround that neutralizes the bug without upgrading Fastify.
3
Upgrade to Fastify 5.12.2 or 6.0.0 — The definitive fix. Schedule within the noisgate 365-day remediation window for MEDIUM-severity findings. If you confirmed your app uses the vulnerable pattern on a security-sensitive endpoint, prioritize sooner.
What doesn't work
  • WAF header-name rules — The attack uses legitimate, properly-formed HTTP headers. There is no malformed syntax or injection payload for a WAF to match on. The bypass is a logic flaw in schema matching, not a protocol violation.
  • Rate limiting — The exploit is a single well-formed HTTP request, indistinguishable from normal traffic. Rate limiting provides no protection.
  • Upgrading only the JSON Schema validator (ajv) — The bug is in Fastify’s schema compilation layer, not in ajv itself. Upgrading ajv alone does not fix the case normalization gap.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo known exploitation. Not listed on CISA KEV as of 2026-09-04.
Proof of ConceptNo public PoC repository identified. The GHSA advisory (GHSA-9q9j-q6p8-xq58) describes the mechanism in sufficient detail to reproduce with a trivial curl command.
EPSS ScoreNot yet scored (CVE published 2026-09-04). Expected to be low given the narrow trigger conditions.
KEV StatusNot listed. No CISA KEV entry.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N — network-accessible, no auth, integrity-only impact. No confidentiality or availability impact.
Affected VersionsFastify < 5.12.2 (all 5.x releases prior). Likely affects 4.x as well if schema compilation shares the same code path, but the advisory only names 5.x.
Fixed Versions5.12.2 and 6.0.0. No backport to 4.x announced.
Scanning / ExposureFastify has ~8–11M weekly npm downloads. However, the vulnerable code path requires use of dependencies in header schemas with mixed-case keys—a pattern likely present in <5% of deployments based on the rarity of this schema construct.
Disclosure Date2026-09-04
Reporterschecthellraiser606, fix by mcollina and UlisesGascon

Sources.

  1. GHSA-9q9j-q6p8-xq58 — Fastify Advisory
  2. Fastify GitHub Releases
  3. NVD — CWE-178: Improper Handling of Case Sensitivity
  4. CVE-2026-33806 — Related Fastify Validation Bypass (GitLab Advisory)
  5. Fastify npm Package
  6. Fastify CVE List — CVE Details
  7. GHSA-247c-9743-5963 — Related Leading-Space Bypass
05 · The Call

Final Verdict
↓ DOWNGRADED to MEDIUM (5.3/10)

Why this verdict

  • Narrow trigger pattern: The bug requires dependencies keyword usage in header schemas with mixed-case nested property names. This is an advanced, uncommon JSON Schema construct. Most Fastify apps use simple required arrays or body validation, not cross-header dependency graphs. Estimated <5% of deployments are affected. Downward pressure: −1.0 from baseline.
  • Integrity-only, no RCE: The CVSS vector explicitly marks C:N and A:N. The attacker bypasses a validation gate but does not gain code execution, data exfiltration, or denial of service directly from this CVE. Actual impact is application-dependent. Downward pressure: −0.5 from baseline.
  • No exploitation evidence: Zero KEV listing, zero known campaigns, no public PoC tooling, EPSS not yet scored. The CVE was disclosed today (2026-09-04). No urgency signal from threat intelligence. Downward pressure: −0.5 from baseline.
  • Role multiplier: Fastify is a general-purpose Node.js web framework. (a) *Low-value role*: dev/test servers—irrelevant. (b) *Typical role*: API backend for a line-of-business app—validation bypass could let malformed requests through, but secondary authorization in hooks or middleware limits blast radius to the single tenant/endpoint. (c) *High-value role*: Fastify as an API gateway or auth-adjacent microservice—if the dependencies schema pattern is the sole authorization gate AND the handler performs a privileged action, the blast radius could be elevated access within that service. However, Fastify is not canonically an identity provider, domain controller, hypervisor, or network edge appliance. The fraction of Fastify installs occupying a high-value role *and* using the vulnerable schema pattern is estimated well below 1%. The floor rule does not override the friction-based downgrade.

Why not higher?

The vendor’s HIGH (7.5) assumes every Fastify instance is vulnerable, but the trigger requires a specific, uncommon schema construct (dependencies with mixed-case nested keys). Without that pattern, the CVE is inert. Additionally, the impact is integrity-only—no RCE, no data leak, no DoS—so even when triggered, the attacker still needs a secondary application-layer flaw to achieve meaningful compromise. No in-the-wild exploitation or public weaponization exists.

Why not lower?

The attack vector is unauthenticated and network-accessible with zero complexity (a single HTTP request). If a deployment does use the vulnerable pattern on a security-sensitive endpoint, the bypass is trivially exploitable with curl. The 8–11M weekly download volume means even a small percentage of vulnerable apps is a non-trivial absolute number. Dropping below MEDIUM would understate the risk for the subset of teams that do rely on header schema dependencies as a security control.

06 · Verification

Crowdsourced verification payload.

Run this on any host where your Fastify application’s package.json or node_modules directory is accessible. No special privileges required. Example: bash check_cve_2026_84428.sh /opt/myapp

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash\n# check_cve_2026_84428.sh - Check for CVE-2026-84428 (Fastify header schema case normalization bypass)\n# Usage: bash check_cve_2026_84428.sh /path/to/app\n# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN\n\nset -euo pipefail\n\nAPP_DIR=\"${1:-.}\"\nPKG_JSON=\"${APP_DIR}/node_modules/fastify/package.json\"\n\nif [ ! -f \"$PKG_JSON\" ]; then\n  echo \"UNKNOWN - fastify not found in ${APP_DIR}/node_modules\"\n  exit 2\nfi\n\nVERSION=$(grep -oP '\"version\":\\s*\"\\K[0-9]+\\.[0-9]+\\.[0-9]+' \"$PKG_JSON\" | head -1)\n\nif [ -z \"$VERSION\" ]; then\n  echo \"UNKNOWN - could not parse fastify version from $PKG_JSON\"\n  exit 2\nfi\n\necho \"Detected fastify version: $VERSION\"\n\nMAJOR=$(echo \"$VERSION\" | cut -d. -f1)\nMINOR=$(echo \"$VERSION\" | cut -d. -f2)\nPATCH=$(echo \"$VERSION\" | cut -d. -f3)\n\n# Fixed in 5.12.2 and 6.0.0\nif [ \"$MAJOR\" -ge 6 ]; then\n  echo \"PATCHED - fastify $VERSION (>= 6.0.0)\"\n  exit 0\nelif [ \"$MAJOR\" -eq 5 ]; then\n  if [ \"$MINOR\" -gt 12 ]; then\n    echo \"PATCHED - fastify $VERSION (> 5.12.x)\"\n    exit 0\n  elif [ \"$MINOR\" -eq 12 ] && [ \"$PATCH\" -ge 2 ]; then\n    echo \"PATCHED - fastify $VERSION (>= 5.12.2)\"\n    exit 0\n  else\n    echo \"VULNERABLE - fastify $VERSION (< 5.12.2)\"\n    exit 1\n  fi\nelif [ \"$MAJOR\" -lt 5 ]; then\n  echo \"UNKNOWN - fastify $VERSION (4.x; advisory only names 5.x but may be affected)\"\n  exit 2\nfi