CVE-2026-22818

Hono-r Among Thieves: Weaponizing JWT Algorithm Confusion in Hono Framework

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 14, 2026·5 min read

Executive Summary (TL;DR)

Hono versions prior to 4.11.4 trust the JWT header's algorithm claim when the server's JWK Set lacks an explicit algorithm definition. An attacker can sign a malicious token using the server's public key as a symmetric HMAC secret (HS256), tricking the server into verifying the signature successfully and granting full access.

A critical authentication bypass in the Hono Web Framework allows attackers to exploit JWT algorithm confusion. By forcing the server to treat a public RSA key as a shared HMAC secret, attackers can forge valid tokens and gain administrative access.

The Hook: Trust Issues in the Fast Lane

Hono markets itself as the "Ultrafast" web framework for the Edges. It is lightweight, performant, and increasingly popular for building APIs on Cloudflare Workers and Deno. But speed often comes at the price of safety, particularly when dealing with the absolute minefield that is the JSON Web Token (JWT) specification.

The core of the problem lies in Hono's jwk (JSON Web Key) middleware. This component acts as the bouncer, fetching cryptographic keys from a remote source (like Auth0 or AWS Cognito) to verify the digital signatures of incoming users. Ideally, this bouncer should be strict, checking ID against a rigorous list of requirements.

Instead, prior to version 4.11.4, the bouncer was a bit too accommodating. It assumed that if the trusted key provider didn't specify how to check the ID, it should just ask the person holding the ID. And as any security researcher knows, you never ask the user how you should verify their credentials.

The Flaw: An Optional Specification Disaster

The root cause stems from a dangerous ambiguity in RFC 7517 (JSON Web Key). The specification states that the alg (algorithm) parameter in a Key Object is optional. Many Identity Providers (IdPs) omit this field in their JWKS endpoints, providing only the Key ID (kid) and the key material (modulus/exponent).

Hono's middleware needed to decide which cryptographic algorithm to use for verification. Its logic flow was essentially:

  1. Look up the key in the JWK Set using the token's kid.
  2. Check if the key object has an alg property.
  3. Fatal Flaw: If the key object lacks an alg, fall back to the alg specified in the incoming JWT header.

This is the classic setup for Algorithm Confusion. The server holds a Public Key (intended for asymmetric verification like RS256). However, if the attacker tells the server "Hey, use HS256 (symmetric HMAC)" via the header, and the server blindly obeys because the JWK didn't say otherwise, the server will attempt to verify the signature using the Public Key as a raw symmetric string (password).

The Code: The Smoking Gun

Let's look at the logic that enabled this. In the vulnerable versions, the verification routine was too permissive regarding the algorithm source.

The Vulnerable Logic (Simplified):

// Inside the JWK verification middleware
const key = findKey(jwks, token.header.kid);
 
// If the JWK doesn't mandate an algorithm, trust the attacker's header
const algorithm = key.alg || token.header.alg;
 
// Verify using the derived algorithm and the key material
const isValid = await verify(token, key, algorithm);

If key.alg is undefined (common in wild configs), algorithm becomes whatever the attacker put in token.header.alg. If the attacker sets alg: HS256, the verify function treats the RSA Public Key content as the HMAC shared secret.

The Fix (Commit 190f6e2): The patch forces developers to be explicit. The middleware now mandates an allowlist and actively forbids symmetric algorithms in this context.

// The patched logic requires an explicit allowlist
if (!options.alg) {
  throw new Error('The "alg" option is required.');
}
 
// Explicitly ban symmetric algorithms for JWK endpoints
if (options.alg.startsWith('HS')) {
   throw new Error('Symmetric algorithms are not allowed.');
}
 
// Ensure the header matches the allowlist, ignoring the header's claim if it deviates
if (!options.alg.includes(token.header.alg)) {
   throw new Error('Algorithm mismatch');
}

The Exploit: Public Key as a Password

Exploiting this requires zero privileged access, just network visibility of the target's JWKS endpoint (which is public by design).

Step 1: Reconnaissance The attacker grabs the server's public keys from https://target.com/.well-known/jwks.json. They verify that the keys lack the alg field.

// Target's JWK
{
  "kty": "RSA",
  "kid": "xyz-123",
  "n": "...base64_modulus...",
  "e": "AQAB"
  // Note: No "alg": "RS256" here!
}

Step 2: Weaponization The attacker constructs a JWT. They set the header to HS256. In the payload, they set "role": "admin".

Step 3: Signing This is the magic trick. The attacker converts the target's RSA Public Key into a PEM string. They then use this public string as the secret key to sign their forged token using HMAC-SHA256.

const jwt = require('jsonwebtoken');
const fs = require('fs');
 
// The public key acts as the shared secret
const publicKeyAsSecret = fs.readFileSync('public_key.pem');
 
const maliciousToken = jwt.sign(
  { sub: 'hacker', role: 'admin' },
  publicKeyAsSecret,
  { 
    algorithm: 'HS256', 
    header: { kid: 'xyz-123' } 
  }
);

Step 4: Execution The attacker sends this token to the API. Hono fetches the key xyz-123. It sees no alg in the JWK. It looks at the header: HS256. It says, "Okay, I'll verify this HMAC signature using the key material I have." Since the server uses the exact same Public Key string to verify that the attacker used to sign, the math checks out. The attacker is now Admin.

The Fix: Closing the Loophole

The remediation in version 4.11.4 is aggressive and introduces a breaking change, which is exactly what was needed. The developers realized that implicit trust in headers is a dead end.

Mitigation Strategy:

  1. Update: Move to Hono 4.11.4 immediately.
  2. Configure: You must now explicitly tell the middleware which algorithms are allowed. If you expect RS256, you must write alg: ['RS256'] in your config.
  3. Sanitize: The update explicitly throws an error if you try to use HS* (symmetric) algorithms in the jwk middleware, preventing accidental misconfigurations where a developer might try to support both.

This forces the application to validate the contract before validating the user, ensuring that asymmetric keys are treated as asymmetric keys, regardless of what the incoming packet claims.

Fix Analysis (1)

Technical Appendix

CVSS Score
8.2/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N

Affected Systems

Hono Web Framework (Node.js)Hono Web Framework (Deno)Hono Web Framework (Cloudflare Workers)Hono Web Framework (Bun)

Affected Versions Detail

Product
Affected Versions
Fixed Version
hono
HonoJS
< 4.11.44.11.4
AttributeDetail
CWE IDCWE-347
Attack VectorNetwork (Remote)
CVSS8.2 (High)
ImpactAuthentication Bypass / Privilege Escalation
Exploit StatusPOC Available
Affected Componenthono/jwk Middleware
CWE-347
Improper Verification of Cryptographic Signature

The product does not verify or incorrectly verifies the cryptographic signature of data, allowing an attacker to modify data without detection.

Vulnerability Timeline

Vulnerability Disclosed
2026-01-13
Patch v4.11.4 Released
2026-01-13
GHSA Advisory Published
2026-01-13

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.