Harden JWT: 8-hour expiry, add JWT vulnerability checks
- Reduce ACCESS_TOKEN_EXPIRE_MINUTES from 24h to 8h (no permanent sessions) - Add JWT_PATTERNS to security_check.py: algorithm=none, verify_exp=False, multi-day timedelta, oversized EXPIRE_MINUTES, hardcoded secret - Add JWT security checklist to security-auditor agent - Document auth/session security items in TODO.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,9 @@ Checks:
|
||||
3. Weak cryptography (MD5, SHA1 for passwords, DES)
|
||||
4. SQL injection risk (f-strings / .format() / % in execute/query/text())
|
||||
5. Missing input sanitization (raw request attributes passed to DB)
|
||||
6. Debug/development flags left in code
|
||||
7. bandit static analysis on Python files
|
||||
6. JWT vulnerabilities (algorithm=none, verify_exp=False, long-lived tokens)
|
||||
7. Debug/development flags left in code
|
||||
8. bandit static analysis on Python files
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -74,6 +75,28 @@ SANITIZATION_PATTERNS = [
|
||||
"raw request attribute passed to DB — route through a Pydantic schema first"),
|
||||
]
|
||||
|
||||
JWT_PATTERNS = [
|
||||
# Algorithm confusion attack — accepting 'none' algorithm
|
||||
(r'algorithms?\s*=\s*\[.*["\']none["\']',
|
||||
"JWT algorithm 'none' accepted — algorithm confusion attack (Critical)"),
|
||||
(r'algorithm\s*=\s*["\']none["\']',
|
||||
"JWT algorithm set to 'none' — algorithm confusion attack (Critical)"),
|
||||
# Disabling expiry verification
|
||||
(r'verify_exp\s*[=:]\s*False',
|
||||
"JWT expiry verification disabled — tokens never expire (Critical)"),
|
||||
(r'options\s*=\s*\{[^}]*["\']verify_exp["\'].*False',
|
||||
"JWT expiry verification disabled in options dict (Critical)"),
|
||||
# Long-lived tokens: timedelta(days=...) in JWT context is suspicious
|
||||
(r'timedelta\s*\(\s*days\s*=\s*[1-9]',
|
||||
"JWT token with multi-day expiry — use hours, not days (High)"),
|
||||
# Overly large EXPIRE_MINUTES constant (>9999 min ≈ 7 days)
|
||||
(r'EXPIRE_MINUTES\s*[=:]\s*[1-9]\d{4,}',
|
||||
"JWT EXPIRE_MINUTES value > 9999 (> 7 days) — reduce token lifetime (High)"),
|
||||
# Hardcoded JWT secret
|
||||
(r'SECRET_KEY\s*=\s*["\'][a-zA-Z0-9_\-]{4,}["\'](?!.*env|.*change)',
|
||||
"possible hardcoded JWT secret — use env var (High)"),
|
||||
]
|
||||
|
||||
DEBUG_PATTERNS = [
|
||||
(r'\bdebug\s*=\s*True\b', "debug=True left in code"),
|
||||
(r'print\s*\(.*password', "possible password printed to stdout"),
|
||||
@@ -85,6 +108,7 @@ ALL_PATTERNS = (
|
||||
+ [("CRYPTO", p, m) for p, m in WEAK_CRYPTO_PATTERNS]
|
||||
+ [("SQLINJ", p, m) for p, m in SQL_INJECTION_PATTERNS]
|
||||
+ [("SANIT", p, m) for p, m in SANITIZATION_PATTERNS]
|
||||
+ [("JWT", p, m) for p, m in JWT_PATTERNS]
|
||||
+ [("DEBUG", p, m) for p, m in DEBUG_PATTERNS]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user