RFC 8725 JWT Security Posture Auditor, Cryptographic Validator & Compliance Test Vector Engine
specter-jwt is a statically-typed Rust command-line utility and library designed for security engineers and backend systems developers to audit JSON Web Tokens (RFC 7515 / RFC 7519) against RFC 8725 (JSON Web Token Best Current Practices), verify HMAC signatures using constant-time primitives, detect weak staging/development signing keys, and synthesize deterministic negative compliance test vectors for OAuth2 / OIDC verification middleware.
| Standard / Identifier | Scope & Control Enforced by specter-jwt |
|---|---|
| RFC 7515 / RFC 7518 | JWS Compact Serialization parsing, RFC 4648 Section 5 Base64URL encoding, HMAC-SHA256/384/512 key size enforcement. |
| RFC 7519 | Temporal claim validation (exp, iat, nbf) and structural claim binding (iss, aud, sub). |
| RFC 8725 Section 3.1 | Algorithm verification posture, rejection of unsecured alg: none permutations, and asymmetric-to-symmetric key confusion detection. |
| RFC 8725 Section 3.2 | Dynamic JWK Set reference (jku, x5u) and inline jwk header inspection. |
| RFC 8725 Section 3.10 | Key Identifier (kid) header parameter hygiene against filesystem path traversal and injection metacharacters. |
| CWE-347 | Improper Verification of Cryptographic Signature (alg: none, empty signature segment, RS256/ES256 to HS256 confusion). |
| CWE-326 / CWE-327 | Inadequate Encryption Strength / Use of a Broken or Risky Cryptographic Algorithm (Shannon entropy and minimum key length checks). |
| CWE-208 | Observable Timing Discrepancy (mitigated via subtle::ConstantTimeEq and zeroize memory scrubbing). |
| CWE-22 / CWE-89 | Improper Limitation of a Pathname to a Restricted Directory (kid traversal vectors on Linux and Windows). |
| CWE-918 | Server-Side Request Forgery (jku / x5u untrusted external URL references). |
+-----------------------------------------------------------------------------------+
| specter-jwt CLI |
| (clap v4 Subcommand Dispatcher) |
+-------------------+-----------------------+-----------------------+---------------+
| | |
v v v
+-----------------------+ +--------------------+ +--------------------------+
| auditor::audit_jwt | | crypto::verify | | vectors::generate_vectors|
| (RFC 8725 Engine) | | (Constant-Time) | | (--confirm-authorized) |
+-----------+-----------+ +---------+----------+ +-------------+------------+
| | |
| | |
+---------------+---------------+ | +-------------+------------+
| - Alg Policy (Sec 3.1) | | | - AlgNone (4 casings) |
| - Header Hygiene (kid/jku/x5u)| | | - KeyConfusion (HS256) |
| - Temporal Bounds (exp/iat) | | | - KidTraversal (Lin/Win) |
| - Unencrypted PII Detection | | | - JkuSsrf Header Vector |
+---------------+---------------+ | +--------------------------+
| v
| +--------------------+
| | - HMAC-SHA256/384 |
| | - HMAC-SHA512 |
| | - subtle::ct_eq |
| | - zeroize::Zeroize |
| | - Rayon ThreadPool |
| +--------------------+
v
+-------------------------------+
| Output Renderers: |
| 1. Deterministic ASCII Table |
| 2. Structured JSON |
| 3. OASIS SARIF v2.1.0 |
+-------------------------------+
| Subcommand | Alias | Description | Safety Gate Required |
|---|---|---|---|
audit |
- | Performs static RFC 8725 compliance and security posture analysis on a JWS token. Supports text, json, and sarif output formats. |
No (Read-only inspection) |
verify |
audit-secret |
Verifies HMAC-SHA256/384/512 signatures in constant time and audits tokens against candidate development wordlists using Rayon worker pools. | Yes (--confirm-authorized-scope for wordlist mode) |
generate-test-vectors |
forge |
Synthesizes deterministic negative compliance unit-test vectors (alg-none, key-confusion, kid-traversal, jku-ssrf) for middleware regression testing. |
Yes (--confirm-authorized-scope mandatory) |
Audit a token and emit a human-readable engineering report:
cargo run --release -- audit \
--token "eyJhbGciOiJub25lIiwia2lkIjoiLi4vLi4vLi4vLi4vZGV2L251bGwifQ.eyJzdWIiOiJhZG1pbiIsImFwaV9rZXkiOiJ0ZXN0LWtleS1leHBvc2VkIn0." \
--format textSample output:
================================================================================
SPECTER-JWT : RFC 8725 SECURITY POSTURE & COMPLIANCE AUDIT REPORT
================================================================================
Compliance Status : FAIL (Non-Compliant Findings Detected)
Risk Score : 100 / 100
Signature Status : Empty / Unsigned (0 bytes)
--------------------------------------------------------------------------------
DECODED JWS HEADER:
{
"alg": "none",
"kid": "../../../../dev/null"
}
--------------------------------------------------------------------------------
DECODED JWS PAYLOAD:
{
"api_key": "test-key-exposed",
"sub": "admin"
}
--------------------------------------------------------------------------------
FINDINGS (7):
[CRITICAL] JWT-ALG-002 | CWE-347 | RFC 8725 Section 3.1
Title : Unsecured JWT Algorithm ('alg: none')
Description : Token declares algorithm 'none' which disables cryptographic integrity verification.
Remediation : Reject 'none' (and all case permutations) in production verification middleware.
[CRITICAL] JWT-HDR-001 | CWE-22 / CWE-89 | RFC 8725 Section 3.10
Title : Hazardous Characters in 'kid' Header Parameter
Description : The 'kid' parameter ('../../../../dev/null') contains filesystem path traversal or command/SQL injection metacharacters.
Remediation : Restrict 'kid' values to a strict alphanumeric/UUID allowlist before key lookup.
[HIGH] JWT-CLM-001 | CWE-613 | RFC 8725 Section 3.8
Title : Missing Expiration Claim ('exp')
Description : Token does not contain an 'exp' claim, rendering it valid indefinitely unless revoked.
Remediation : Always include and enforce a bounded 'exp' timestamp on bearer tokens.
================================================================================
Export findings in SARIF v2.1.0 for GitHub Advanced Security / CI pipelines:
cargo run --release -- audit \
--token "eyJhbGciOiJub25lIiwia2lkIjoiLi4vLi4vLi4vLi4vZGV2L251bGwifQ.eyJzdWIiOiJhZG1pbiIsImFwaV9rZXkiOiJ0ZXN0LWtleS1leHBvc2VkIn0." \
--format sarifVerify a known secret and evaluate its Shannon entropy against RFC 7518 minimum key length guidelines:
cargo run --release -- verify \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEwNDIiLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5pbnRlcm5hbCIsImF1ZCI6ImFwaS1nYXRld2F5IiwiaWF0IjoxNzMwMDAwMDAwLCJleHAiOjE3MzAwMDM2MDB9.8n_qD1_r6mQ3zU9wP5xK2vL7jT4cH8bF1yG0sA6eW2o" \
--secret "staging-jwt-secret-2025"Audit a staging token against a dictionary of default development secrets using multi-threaded constant-time evaluation:
cargo run --release -- audit-secret \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEwNDIiLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5pbnRlcm5hbCIsImF1ZCI6ImFwaS1nYXRld2F5IiwiaWF0IjoxNzMwMDAwMDAwLCJleHAiOjE3MzAwMDM2MDB9.8n_qD1_r6mQ3zU9wP5xK2vL7jT4cH8bF1yG0sA6eW2o" \
--wordlist samples/sample_wordlist.txt \
--threads 4 \
--confirm-authorized-scopeGenerate cross-platform kid path hygiene test vectors for Linux (../../../../dev/null) or Windows (..\..\..\..\Windows\win.ini) to verify that middleware rejects unvalidated header paths:
cargo run --release -- generate-test-vectors \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEwNDIiLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5pbnRlcm5hbCIsImF1ZCI6ImFwaS1nYXRld2F5IiwiaWF0IjoxNzMwMDAwMDAwLCJleHAiOjE3MzAwMDM2MDB9.8n_qD1_r6mQ3zU9wP5xK2vL7jT4cH8bF1yG0sA6eW2o" \
--mode kid-traversal \
--target-os windows \
--set-claim role=auditor \
--confirm-authorized-scopeGenerate an asymmetric-to-symmetric algorithm confusion test vector (RS256 -> HS256) using a sample public key PEM:
cargo run --release -- generate-test-vectors \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEwNDIiLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5pbnRlcm5hbCIsImF1ZCI6ImFwaS1nYXRld2F5IiwiaWF0IjoxNzMwMDAwMDAwLCJleHAiOjE3MzAwMDM2MDB9.8n_qD1_r6mQ3zU9wP5xK2vL7jT4cH8bF1yG0sA6eW2o" \
--mode key-confusion \
--public-key samples/sample_rsa_public.pem \
--confirm-authorized-scopecargo fmt --all -- --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --releaserustup target add x86_64-unknown-linux-gnu
cargo build --release --target x86_64-unknown-linux-gnuOn a Windows host with the MSVC Build Tools:
rustup target add x86_64-pc-windows-msvc
cargo build --release --target x86_64-pc-windows-msvcOr cross-compiling from Linux using cargo-xwin or MinGW-w64:
rustup target add x86_64-pc-windows-msvc
cargo xwin build --release --target x86_64-pc-windows-msvcRun the automated repository hygiene check before committing changes:
./scripts/security-audit.shMIT License.