Why AI tools produce this: AI coding tools rarely emit this on their own, but it still slips into assisted edits.
Why this matters
When the attacker controls the key, they sign their own forged token and supply the matching key, so every token "verifies", a complete authentication bypass (CWE-347, Improper Verification of Cryptographic Signature).
The verification key must be fixed server-side. Resolve it from trusted configuration, a keystore, or a vetted key set keyed by a validated kid, never from request.getParameter(...) / request.getHeader(...) or a @RequestParam / @RequestHeader value.
VULNERABLE
vulnerable.java
import com.nimbusds.jose.crypto.MACVerifier;import com.nimbusds.jwt.SignedJWT;import io.jsonwebtoken.Jwts;import jakarta.servlet.http.HttpServletRequest;class TokenVerifier { // jjwt: the verification key comes straight from a request parameter. Object jjwtParam(HttpServletRequest request, String token) { String key = request.getParameter("key"); // ruleid: auth.java.jwt.untrusted-verify-key return Jwts.parser().setSigningKey(key).build().parseSignedClaims(token); } // jjwt (0.12 API): the key comes from a request header. Object jjwtHeader(HttpServletRequest request, String token) { byte[] secret = request.getHeader("X-Key").getBytes(); // ruleid: auth.java.jwt.untrusted-verify-key return Jwts.parser().verifyWith(io.jsonwebtoken.security.Keys.hmacShaKeyFor(secret)) .build().parseSignedClaims(token); } // nimbus: the HMAC secret handed to the verifier is request-controlled. boolean nimbus(HttpServletRequest request, SignedJWT jwt) throws Exception { byte[] secret = request.getParameter("secret").getBytes(); // ruleid: auth.java.jwt.untrusted-verify-key return jwt.verify(new MACVerifier(secret)); }}
SAFE
safe.java
import io.jsonwebtoken.Jwts;import io.jsonwebtoken.security.Keys;import jakarta.servlet.http.HttpServletRequest;import java.security.Key;import java.security.KeyStore;import javax.crypto.SecretKey;class TokenVerifier { // Key resolved from server-side configuration — never from the request. Object fromConfig(String token) { SecretKey key = Keys.hmacShaKeyFor(System.getenv("JWT_SECRET").getBytes()); // ok: auth.java.jwt.untrusted-verify-key return Jwts.parser().verifyWith(key).build().parseSignedClaims(token); } // A `kid` from the request only selects a pre-registered key from a // keystore; the key handed to the parser is trusted, not attacker-supplied. Object byTrustedKid(HttpServletRequest request, KeyStore ks, String token) throws Exception { String kid = request.getParameter("kid"); Key key = ks.getKey(kid, null); // ok: auth.java.jwt.untrusted-verify-key return Jwts.parser().setSigningKey(key).build().parseSignedClaims(token); }}
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.