Proof/CVEs & advisories/GHSA-g3jj-5cmm-3hxx
A public key became a shared secret.
An RSA public key is safe to publish because it verifies signatures without creating them. That model collapses the moment the same bytes are accepted as an HMAC secret — which is what fast-jwt 6.2.4 did with raw JWK JSON.
JWT verification has two linked inputs: the token’s signature algorithm, and the semantic type of the verification key. Losing the second turns the first into an attacker’s choice.
The selected JWT algorithm family must be cryptographically bound to the semantic key type; asymmetric public material must never fall back to an HMAC byte string.
The vulnerable deployment prerequisites are specific:
- the application supplies raw serialized JWK/JWKS JSON as a string or buffer rather than converting it into a native asymmetric key object;
- the verifier accepts HS256 alongside an asymmetric family, or lets fast-jwt infer allowed algorithms; and
- the attacker knows the exact serialized public-key bytes used by the verifier, including property ordering and whitespace when a raw string is used.
An RS256-only verifier is not affected by the demonstrated HS256 forgery path.
In fast-jwt 6.2.4, algorithm detection distinguished recognizable PEM and certificate material from other strings. A non-empty string that was not recognized as PEM fell into the generic HMAC-secret branch:
} else if (!publicKeyPemMatch && !trimmedKey.includes(publicKeyX509CertMatcher)) {
// Not a PEM, assume a plain secret
return hsAlgorithms
}Raw RSA, EC or OKP JWK JSON is not PEM and contains no X.509 header. The verifier therefore loses the semantic information that this string represents public asymmetric key material — even though the JSON’s own kty field says so explicitly.
Once the key is categorized as a secret, an HS256 token using the same serialized JSON bytes as its HMAC key is internally consistent from the verifier’s mistaken point of view.
Verifier is configured with raw public JWK JSON
A serialized string or buffer, not a native asymmetric key object.
An HS algorithm is allowed or inferred
Either a mixed-family allowlist, or algorithm inference.
fast-jwt classifies the JSON as an HMAC secret
The “not PEM” branch discards the asymmetric semantics.
The attacker obtains the same public bytes
They are public by design — that is the point of a public key.
Attacker-selected claims are signed with HS256
Using the serialized public JWK string as the HMAC key.
The vulnerable verifier accepts the forged token
No private key was ever needed.
RS256-only verifier
Rejects the forged HS256 token — establishing that this is confusion, not signature forgery.
Mixed / inferred families
Exact 6.2.4 accepts the attacker-selected claims when HS256 is allowed or inferred alongside the asymmetric family.
6.3.0
Upstream regression tests executed locally and passed; asymmetric JSON structures are recognized before the secret fallback.
The key parser used representation shape as a proxy for key semantics. “Not recognizable PEM” became “plain symmetric secret,” even when the string was structured JSON whose kty explicitly identified RSA, EC or OKP public-key material.
Cryptographic policy should fail closed when the key’s semantic type and the requested algorithm family disagree. Falling back from an unrecognized structured key to a generic secret converts intentionally public bytes into authentication material.
Follow the key, not the file format.
Key-detection code is a natural place for security to leak, because it answers a parsing question and a policy question at the same time. The hypothesis was simple: find the branch that gives up on identifying a key and picks a default.
Source mapping
Read the key-classification path and locate every fallback branch.
Semantics hypothesis
Ask what happens when structured asymmetric material is unrecognized rather than malformed.
Runtime construction
Forge HS256 claims using only the public JWK bytes; never touch the private key.
Skeptic gate
Run the RS256-only control so the result reads as key-type confusion, not signature forgery.
Promotion and disclosure
Keep the published affected range as the publisher scoped it; test only owned keys.
The fixing commit is 10f9591349199ed2ab9fa1748ce92cdca697f6cf, released in fast-jwt 6.3.0. It recognizes JSON-looking key strings before the generic raw-secret fallback and rejects asymmetric structures being treated as symmetric key material. The guarded structures are:
- a top-level JWK with
ktyofRSA,ECorOKP; - a JWKS containing asymmetric keys; and
- a bare array containing asymmetric JWK values.
Symmetric JWKs using kty: "oct" and ordinary opaque HMAC secrets remain valid. An explicitly all-HS caller is treated as an intentional assertion that the supplied material is meant to be symmetric; the fix targets the mixed-family and inferred cases where asymmetric semantics would otherwise be silently lost.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:NAttack complexity is elevated because exploitation depends on a particular key representation and algorithm configuration, including knowledge of the exact serialized bytes used as the verifier key. Downstream effect depends on what the consuming application trusts from JWT claims — commonly impersonation, authorization bypass, or access granted by forged roles or identities.
| Scope | Value | Basis |
|---|---|---|
| Public affected version | 6.2.4 | advisory intentionally limits the range |
| Fixed | 6.3.0 | exact npm artifacts and matching tags inspected |
| Historical lineage | e3ff09f07b55414e1fdaad2b8f225aa94832b45a | older refactor introducing the non-PEM-to-HMAC inference shape |
That lineage does not expand the published affected range. Earlier releases were explicitly not assessed for the advisory and are not claimed affected here.
Upgrade to fast-jwt 6.3.0 or later. Applications should also make their intended cryptographic model explicit:
- convert JWK/JWKS data into native asymmetric key objects where appropriate;
- restrict verifiers to the expected algorithm family rather than mixed symmetric/asymmetric allowlists unless there is a compelling reason;
- reject keys whose semantic type conflicts with the selected JWT algorithm;
- avoid “unknown structured key ⇒ raw secret” fallback behaviour entirely.
Regression tests should cover RSA, EC, OKP and oct JWK values as top-level JWKs, JWKS documents, arrays, PEM strings and opaque secrets — across both inferred and explicit algorithm lists.
- GHSA-g3jj-5cmm-3hxx — fast-jwt advisory and public PoC
- fast-jwt repository and release history
- fast-jwt release history
Credit: Discovered and reported by Charles Vosburgh. Research was AI-assisted through source mapping, hypothesis generation, release comparison and evidence organization; final validation, disclosure coordination, severity calibration and publication review remained human.