v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.hono.jwt-hardcoded-secret

Hono's jwt() middleware from hono/jwt is configured with a hard-coded secret string literal.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

That key signs and verifies every session token: committed to git it is one search away from compromise, and anyone who reads it can forge a valid token for any user (CWE-798).

Load the secret from the environment / Workers binding instead and add a placeholder to .env.example: app.use('/auth/', jwt({ secret: c.env.JWT_SECRET })) app.use('/auth/', jwt({ secret: process.env.JWT_SECRET })) Use at least 32 characters for HMAC algorithms, and rotate the leaked value out of source control.

(The sign()/verify() helpers with a literal secret are covered by auth.jwt.weak-secret; this rule targets the Hono middleware config, which that rule does not see.)

VULNERABLE
vulnerable.ts
import { Hono } from 'hono';
import { jwt } from 'hono/jwt';

const app = new Hono();

// ruleid: auth.hono.jwt-hardcoded-secret
app.use('/auth/*', jwt({ secret: 'it-is-very-secret' }));

// ruleid: auth.hono.jwt-hardcoded-secret
app.use('/admin/*', jwt({ secret: 'password123', alg: 'HS256' }));
SAFE
safe.ts
import { Hono } from 'hono';
import { jwt } from 'hono/jwt';

const app = new Hono<{ Bindings: { JWT_SECRET: string } }>();

// Secret sourced from the Workers binding / environment — not a literal.
app.use('/auth/*', (c, next) => jwt({ secret: c.env.JWT_SECRET })(c, next));
app.use('/admin/*', (c, next) => jwt({ secret: process.env.JWT_SECRET!, alg: 'HS256' })(c, next));

// Placeholder stub, not a real secret — allow-listed.
app.use('/api/*', (c, next) => jwt({ secret: 'your-jwt-secret' })(c, next));

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

// oauthlint-disable-next-line auth.hono.jwt-hardcoded-secret -- <reason>

References

https://hono.dev/docs/middleware/builtin/jwt ↗https://hono.dev/docs/helpers/jwt ↗https://cwe.mitre.org/data/definitions/798.html ↗