# Improper Verification of Cryptographic Signature (CWE-347) The product does not verify, or incorrectly verifies, the cryptographic signature for data. - Prevalence: High Frequently exploited - Impact: Critical 1 critical-severity rules - Prevention: Documented 4 fix examples **OWASP:** Cryptographic Failures (A02:2021-Cryptographic Failures) - #2 ## Description Cryptographic signatures are used to verify the authenticity and integrity of data. When signature verification is missing or incorrectly implemented, attackers can forge or tamper with data. ## Prevention Prevention strategies for Improper Signature Verification based on 4 Shoulder detection rules. ### Key Practices - Use of jwt ### Python Load JWT secret from environment and explicitly specify allowed algorithms Always specify allowed algorithms explicitly when decoding JWT tokens ### Go Validate JWT algorithm explicitly, use strong secrets, and set expiration ### Node.js Use jwt.verify() instead of jwt.decode() to validate token signatures ## Warning Signs - [HIGH] JWT implementation has security vulnerabilities - [HIGH] JWT security issues in FastAPI applications including: - Weak or hardcoded secrets - Missing algorit - [HIGH] use of jwt - [CRITICAL] JWT tokens decoded without algorithm verification or accepting the 'none' algorithm, allowing token ## Consequences - Bypass Protection Mechanism - Execute Unauthorized Code - Modify Application Data ## Mitigations - Always verify signatures before trusting data - Use well-tested cryptographic libraries for signature verification - For JWT, always verify the signature and validate the algorithm ## Detection - Total rules: 4 - Critical: 1 - Languages: python, go, javascript, typescript ## Rules by Language ### Python (2 rules) - **FastAPI JWT Security Issues** [HIGH]: Detects JWT security issues in FastAPI applications including: - Weak or hardcoded secrets - Missing algorithm verification - Insufficient token validation - Insecure token storage patterns - Remediation: Load JWT secret from environment and explicitly specify the algorithm. ```python from pydantic_settings import BaseSettings from jose import jwt class Settings(BaseSettings): SECRET_KEY: str ALGORITHM: str = "HS256" settings = Settings() def decode_token(token: str): return jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM]) ``` Learn more: https://shoulder.dev/learn/python/cwe-347/jwt-security - **JWT Algorithm Confusion Attack** [CRITICAL]: Detects JWT tokens decoded without algorithm verification or accepting the 'none' algorithm, allowing token forgery. - Remediation: Always specify allowed algorithms explicitly when decoding JWT tokens. ```python payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) ``` Learn more: https://shoulder.dev/learn/python/cwe-347/jwt-algorithm-confusion ### Go (1 rules) - **JWT Security Vulnerabilities** [HIGH]: JWT allows "none" algorithm, uses weak secret, or lacks expiration. - Remediation: Validate algorithm explicitly and set token expiration. ```go token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected method: %v", token.Header["alg"]) } return []byte(os.Getenv("JWT_SECRET")), nil }) ``` Learn more: https://shoulder.dev/learn/go/cwe-347/jwt-vulnerabilities ### Javascript (1 rules) - **JWT Decode Without Verification** [HIGH]: Detects use of jwt.decode() without proper verification, leading to authentication bypass. jwt.decode() decodes a JWT token WITHOUT verifying its signature. This means an attacker can create a token with any payload they want, and the application will trust it. Common mistakes: - Using jwt.decode() instead of jwt.verify() - Decoding token for inspection then trusting the payload - Using decoded payload for authorization decisions The decoded payload should NEVER be trusted for security decisions without verification. - Remediation: Use jwt.verify() instead of jwt.decode() to validate the signature: ```javascript const jwt = require('jsonwebtoken'); app.post('/api/auth/verify', (req, res) => { const { token } = req.body; try { const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['RS256'] }); res.json({ user: decoded }); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }); ``` Learn more: https://shoulder.dev/learn/javascript/cwe-347/jwt-decode-without-verify ### Typescript (1 rules) - **JWT Decode Without Verification** [HIGH]: Detects use of jwt.decode() without proper verification, leading to authentication bypass. jwt.decode() decodes a JWT token WITHOUT verifying its signature. This means an attacker can create a token with any payload they want, and the application will trust it. Common mistakes: - Using jwt.decode() instead of jwt.verify() - Decoding token for inspection then trusting the payload - Using decoded payload for authorization decisions The decoded payload should NEVER be trusted for security decisions without verification. - Remediation: Use jwt.verify() instead of jwt.decode() to validate the signature: ```javascript const jwt = require('jsonwebtoken'); app.post('/api/auth/verify', (req, res) => { const { token } = req.body; try { const decoded = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['RS256'] }); res.json({ user: decoded }); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }); ``` Learn more: https://shoulder.dev/learn/javascript/cwe-347/jwt-decode-without-verify