Oct 1, 2026·8 min read·4 visits
A shallow header-schema normalization bug in Fastify < 5.12.2 allows unauthenticated remote attackers to bypass critical conditional header validation rules, silently skipping security checks if trigger headers are defined in mixed-case.
A validation bypass vulnerability exists in Fastify web framework prior to version 5.12.2. The flaw stems from shallow normalization of header validation schemas, which fails to lowercase nested or conditional schema rules (like JSON Schema dependencies or dependentRequired) defined in mixed or canonical casing. Consequently, because Node.js normalizes incoming HTTP request headers to lowercase, the compiled validator fails to match these headers against the un-normalized mixed-case schema triggers, silently skipping conditional checks and allowing unauthenticated attackers to bypass authorization or security headers.
Fastify is a highly optimized web framework for Node.js that prioritizes performance and low overhead. To enforce data integrity and structure HTTP requests, developers commonly declare validation schemas for different request components, including route headers. When incoming requests are received, Fastify leverages schema validation engines like Ajv to verify that the headers comply with specified formats, constraints, and dependencies before passing execution to the route handler.
HTTP headers are case-insensitive by specification according to RFC 9110, meaning headers like X-Admin and x-admin must be treated as identical. To handle this, Node.js automatically normalizes all incoming request headers to lowercase inside the request.headers object. Fastify aligns with this behavior by lowercasing the keys in developer-defined header schemas during the pre-compilation phase, ensuring that the validator matches incoming lowercase request data against the schema parameters.
CVE-2026-84428 represents a validation bypass vulnerability in Fastify's schema preprocessing logic where normalization was performed only on a shallow level. If a developer declared case-insensitive conditional schema keywords such as dependencies or dependentRequired using canonical or mixed casing, Fastify failed to recursively lowercase these internal subschema properties. Consequently, the validator was compiled with mixed-case rules that failed to match the incoming lowercased headers, allowing attackers to bypass validation rules designed to enforce dependent or mandatory parameters.
The root cause of CVE-2026-84428 lies in the shallow traversal of header validation schemas prior to compilation in Fastify's core validation module (lib/validation.js). Specifically, the framework's schema normalization utility only converted the primary keys inside the top-level properties object and the root-level required array to lowercase. It did not recursively walk the schema to find other properties that referenced header names.
This behavior becomes problematic when developers utilize JSON Schema draft features to establish conditional requirements. Keywords like JSON Schema Draft 7 dependencies or Draft 2019-09 dependentRequired and dependentSchemas are designed to enforce validation rules based on the presence of certain keys. When these structures are defined with mixed-case or canonical header names, they remain unchanged after Fastify's shallow normalization pass.
During execution, the JSON Schema validator parses the incoming headers, which have already been lowercased by Node.js. When the validator encounters a lowercased header, it looks for any dependency constraints matching that lowercase key in the compiled schema. Because the dependency triggers in the schema were not normalized and remain in mixed-case, the validator finds no corresponding rule and silently skips the dependency check, failing to enforce the required conditional headers.
Prior to the release of the patch, Fastify performed a simplistic object-cloning operation to normalize headers. The framework initialized a shallow copy of the schema's root properties and lowercased only those specific paths as demonstrated in the following snippet:
// Vulnerable implementation in lib/validation.js
const headersSchemaLowerCase = {}
Object.keys(headers).forEach(k => { headersSchemaLowerCase[k] = headers[k] })
if (headersSchemaLowerCase.required instanceof Array) {
headersSchemaLowerCase.required = headersSchemaLowerCase.required.map(h => h.toLowerCase())
}
if (headers.properties) {
headersSchemaLowerCase.properties = {}
Object.keys(headers.properties).forEach(k => {
headersSchemaLowerCase.properties[k.toLowerCase()] = headers.properties[k]
})
}To resolve this issue, the maintainers implemented a recursive function named lowerCaseHeadersSchema which traverses the entire JSON Schema tree. This function maps and translates keys in every nested object, conditional block, and logical combinator, ensuring that properties inside dependencies, dependentRequired, and dependentSchemas are thoroughly normalized. The updated implementation iterates recursively as shown below:
// Patched implementation in lib/validation.js
function lowerCaseHeadersSchema (schema) {
if (Array.isArray(schema)) {
return schema.map(lowerCaseHeadersSchema)
}
if (schema === null || typeof schema !== 'object') {
return schema
}
const result = {}
for (const key of Object.keys(schema)) {
const value = schema[key]
switch (key) {
case 'properties': {
// Recurse and lowercase keys of the properties map
const normalized = {}
for (const prop of Object.keys(value)) {
normalized[prop.toLowerCase()] = lowerCaseHeadersSchema(value[prop])
}
result.properties = normalized
break
}
case 'required':
result.required = Array.isArray(value) ? value.map(name => name.toLowerCase()) : value
break
case 'dependencies': {
// Normalize trigger keys and dependent property lists
const normalized = {}
for (const dep of Object.keys(value)) {
const depValue = value[dep]
if (Array.isArray(depValue)) {
normalized[dep.toLowerCase()] = depValue.map(name => name.toLowerCase())
} else {
normalized[dep.toLowerCase()] = lowerCaseHeadersSchema(depValue)
}
}
result.dependencies = normalized
break
}
// Additional cases handle dependentSchemas, dependentRequired, allOf, anyOf, etc.
}
}
return result
}While the recursive implementation correctly handles inline schemas, the maintainers identified a limitation: schemas referencing external definitions via $ref cannot be safely mutated. Modifying shared external schemas could disrupt other route components that require case preservation (e.g., body parameters). Consequently, Fastify introduced findExternalHeaderRef to analyze schemas for external references and emit warning code FSTSEC002 if any are detected.
Exploitation of CVE-2026-84428 requires a target endpoint that uses case-sensitive validation conditions on incoming HTTP headers. An attacker can craft a request that triggers a validation bypass if they omit the required secondary security header while providing the primary conditional header.
Consider an application that uses a header-triggered privileged flow. The schema mandates that if the client sends X-Admin: true, they must also supply a secret authorization key in X-Admin-Token. This behavior is defined programmatically using a dependencies statement in Fastify:
// Vulnerable validation definition
headers: {
type: 'object',
properties: {
'X-Admin': { type: 'string', const: 'true' },
'X-Admin-Token': { type: 'string', const: 'secret-token-1234' }
},
dependencies: {
'X-Admin': ['X-Admin-Token']
}
}To execute the exploit, an attacker submits a GET request containing the primary header X-Admin: true while completely omitting X-Admin-Token. Because Node.js normalizes the incoming headers, the schema validator evaluates the request against x-admin. Since the dependency keyword specifies X-Admin, the validator skips the verification block entirely, executing the route handler and granting administrative access without credentials.
An administrative bypass of this nature is reproducible programmatically. Security engineers can verify whether an endpoint is vulnerable by using a local test harness to send mismatched header payloads and monitoring whether Fastify accepts requests that should be rejected with a 400 Bad Request response.
The impact of CVE-2026-84428 is classified as High, with a CVSS base score of 7.5. The vulnerability allows unauthenticated remote attackers to bypass application-level validation logic, potentially circumventing defense mechanisms designed to protect privileged routes. If an application uses conditional header checks to verify authentication tokens, tenant routing identifiers, or environment contexts, the bypass can result in unauthorized access to sensitive application components.
Because the flaw resides entirely within the validation compilation phase, exploitation does not leave typical application error signatures. The target application processes the requests as syntactically and semantically valid, meaning security teams cannot detect exploit attempts using standard server logs unless they specifically audit header structures on incoming traffic.
This vulnerability has not been observed in active exploitation, nor has it been added to CISA's Known Exploited Vulnerabilities catalog. However, the presence of public proof-of-concept tests within the framework repository increases the likelihood of reverse engineering and targeted attacks against outdated deployments of Fastify.
The primary remediation path is to upgrade all Fastify installations to version 5.12.2 or later. This ensures that the schema compiler utilizes the recursive lowerCaseHeadersSchema utility to properly normalize all internal and conditional properties prior to validation.
In scenarios where immediate patching is not feasible, developers must manually rewrite schemas to avoid mixed-case definitions. Modifying all header validation schemas to use strictly lowercase keys in both the properties block and any conditional keywords (such as dependencies or dependentRequired) will align the validation rules with the pre-compiled headers, neutralizing the bypass vector.
Additionally, developers must audit their applications for the FSTSEC002 warning code. If a headers schema references external definitions via $ref, Fastify will skip automatic normalization to prevent side effects on other schema consumers. To resolve this, external schemas containing header validations should be inlined or defined locally within the route schema.
For defense-in-depth, security teams should implement auxiliary middleware validation hooks. Standardizing manual verification of critical security headers inside a preHandler hook provides a secondary validation layer that does not rely on declarative schema engines, ensuring consistent protection against parser-level discrepancies.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Fastify fastify | < 5.12.2 | 5.12.2 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Improper Handling of Case Sensitivity (CWE-178) |
| Attack Vector | Network (AV:N) |
| CVSS Base Score | 7.5 (High) |
| EPSS Score | 0.00524 (Percentile: 42.21%) |
| Exploit Maturity | Proof-of-Concept (PoC) |
| CISA KEV Status | Not Listed |
The software performs a case-sensitive comparison of an identifier or resource name that should be case-insensitive, leading to validation gaps.
An authorization bypass and path traversal vulnerability exists in the SiYuan knowledge workspace platform. The vulnerability is located in the '/api/file/getUniqueFilename' endpoint inside the 'github.com/siyuan-note/siyuan/kernel' package. Under default configurations, this route is exposed to users who satisfy basic authentication middleware checks, which includes anonymous readers in publish mode. By supplying unvalidated absolute paths, remote attackers can verify the existence of files and directories across the host operating system, establishing a high-fidelity file existence oracle.
A highly critical Regular Expression Denial of Service (ReDoS) vulnerability in basic-ftp, an FTP client library for Node.js. In versions prior to 6.2.1, a malicious or compromised FTP server can exploit this vulnerability to force the FTP client to consume quadratic CPU time during directory parsing. This issue blocks the single-threaded Node.js event loop, freezing the application process and leading to a complete Denial of Service (DoS).
An uncontrolled resource consumption vulnerability in the russh library allows remote authenticated attackers to exhaust server memory (heap) by flooding channel open requests during a stalled key re-exchange (rekeying) process, causing a denial of service via Out-of-Memory (OOM) termination.
A critical memory handling vulnerability exists in the pageant crate, a workspace component of the Rust-based russh SSH client library, during communication with the PuTTY Pageant SSH agent on Windows systems. Prior to version 0.2.3, the library's shared memory parsing logic blindly trusted a peer-controlled, 32-bit big-endian response length field. This allows local attackers running within the same user session to trigger out-of-bounds reads or execute an out-of-memory crash of the client application.
CVE-2026-84469 is a high-severity request validation bypass vulnerability in the Fastify Node.js web framework. In versions prior to 5.12.2, Fastify uses loose truthiness checks to decide whether to compile request schemas. When a component (such as the body) is explicitly configured with a boolean 'false' schema—which under JSON Schema Draft 7 acts as a 'deny-all' constraint—Fastify's internal logic evaluates this as a falsy value and skips compilation entirely. This allows unauthenticated remote attackers to send arbitrary payloads to these endpoints, bypassing validation checks and directly executing backend route handlers.
An authentication bypass vulnerability in the Fastify web framework allows remote attackers to access private custom not-found handlers by submitting requests with malformed URLs. This bypasses the typical request lifecycle and its associated authorization hooks.