Skip to content

Commit fd44e39

Browse files
ericelliottCopilot
andauthored
Enhance JWT security guidelines and recommendations (#62)
* Enhance JWT security guidelines and recommendations Expanded security guidelines for JWT usage, including session state, storage, transport, algorithm, verification failure handling, token purpose, key handling, claims validation, authorization, cookie hardening, and lifetime. * Update ai/rules/security/jwt-security.mdc Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
1 parent ed4c862 commit fd44e39

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

ai/rules/security/jwt-security.mdc

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,54 @@ alwaysApply: false
77
**AVOID JWT if you can.** Prefer opaque tokens with server-side sessions.
88

99
Patterns {
10-
(token in localStorage or sessionStorage) => Critical: XSS vulnerable. Use httpOnly Secure SameSite cookies.
11-
(JWT 'none' algorithm) => Critical: Signature bypass. Use RS256/ES256.
10+
## Session State
11+
any(refresh token rotation, refresh reuse detection, jti denylist, jti revocation,
12+
token bound to session, token bound to device, logout invalidates token server-side)
13+
=> Critical: Prefer opaque tokens with server-side sessions. You're tracking state anyway.
14+
15+
## Storage & Transport
16+
(token in localStorage or sessionStorage) => Critical: XSS vulnerable. Use httpOnly Secure SameSite=Strict cookies.
17+
(token in URL or query params) => Critical: Leaks via logs, Referer, browser history, analytics.
18+
(token logged or sent to analytics) => Critical: Scrub tokens from all logging pipelines.
19+
(SameSite=None or missing CSRF protection) => Critical: CSRF exposure. Use SameSite=Strict or add CSRF tokens.
20+
21+
## Algorithm & Signature
22+
(JWT 'none' algorithm) => Critical: Signature bypass. Reject unsigned tokens.
1223
(JWT verification disabled) => Critical: Always verify signatures.
1324
(jwt.decode without verify) => Critical: Use jwt.verify().
14-
(JWT expiration ignored) => Critical: Always check expiration.
15-
(HS256 shared across services) => Critical: Use asymmetric algorithms.
16-
(access token lifetime >= 1 day) => Warn: Use short-lived tokens + refresh rotation.
17-
(JWT detected) => Warn: Consider opaque tokens + server sessions.
18-
}
25+
(alg from token used to select verification) => Critical: Alg confusion. Strict allowlist + key type must match algorithm.
26+
(HS256 or symmetric algorithm) => Critical: Use asymmetric algorithms (RS256/ES256).
27+
28+
## Verification Failure Handling
29+
(verification failure allows anonymous access) => Critical: Fail closed. Invalid token = no access.
30+
(verification failure allows partial or degraded access) => Critical: Fail closed. Invalid token = no access.
31+
32+
## Token Purpose
33+
(ID token used as access token) => Critical: Wrong token type. Use access tokens (typ: at+jwt) for API auth.
34+
(typ header not validated) => Critical: Reject tokens without expected typ. Prevents token confusion.
35+
36+
## Key Handling
37+
(kid used to fetch key from untrusted source) => Critical: SSRF/key injection. Allowlist kid values.
38+
(JWKS URL derived from iss without strict allowlist) => Critical: Attacker-controlled keys. Pin JWKS URLs.
39+
(JWKS endpoint not pinned or cached) => Warn: Cache JWKS with TTL. Validate kid against known set.
40+
(multi-issuer: verification keys shared across issuers) => Critical: Issuer key isolation required. One keyset per issuer.
41+
42+
## Claims Validation
43+
(iss not validated) => Critical: Confused deputy. Verify issuer matches expected value.
44+
(aud not validated) => Critical: Token reuse across services. Verify audience includes this service.
45+
(exp not validated) => Critical: Always check exp claim.
46+
(nbf present and not validated) => Critical: If present, must validate. Reject on failure.
47+
(iat present and not validated) => Critical: If present, must validate. Reject on failure.
48+
(nbf and iat not checked when absent) => Warn: Consider requiring nbf/iat. Validate with ≤60s clock skew.
49+
50+
## Authorization
51+
(roles or scopes trusted without server check) => Critical: Claims are assertions, not policy. Server must enforce.
52+
53+
## Cookie Hardening
54+
(cookie missing __Host- prefix) => Warn: Use __Host- to enforce Secure, Path=/, no Domain.
55+
(cookie Domain set to parent domain) => Warn: Subdomain hijacking. Omit Domain or use __Host-.
1956

20-
If JWT required {
21-
- Asymmetric algorithms (RS256/ES256)
22-
- Short expiration (≤15 min for access tokens)
23-
- httpOnly Secure SameSite cookies
24-
- CSRF protection
25-
- Refresh token rotation
57+
## Lifetime
58+
(access token lifetime >= 1 day) => Critical: Max 15 min for stateless JWT.
59+
(access token lifetime > 15 min and < 1 day) => Warn: Shorter is better. 15 min max recommended.
2660
}

0 commit comments

Comments
 (0)