Conversation
mukul975
left a comment
There was a problem hiding this comment.
Genuinely useful expansion — the recon phase and the sig2n routing are additions I want. Blocking on the CVE citations and one function that cannot execute.
CVE-2022-23529 is Rejected at NVD. The record reads "DO NOT USE THIS CANDIDATE NUMBER ... The issue is not a vulnerability." SKILL.md:332 cites it as live guidance and describes it as "alg:none, key confusion, jku", where the underlying GHSA is RCE via a caller-controlled secretOrPublicKey. Please remove or re-cite it.
Two more mislabelled:
CVE-2015-9235— NVD: jsonwebtoken < 4.2.2, RS/ES to HS key confusion. This PR calls it "node-jws alg:none bypass" at :328, heads a section "KID Empty File / Empty Key Bypass (CVE-2015-9235 family)" at :222, and attaches it to a PyJWT empty-key behaviour at :315. Three different claims, none matching the record.CVE-2017-11424— NVD: PyJWT <= 1.5.0 PEM-detection bypass enabling key confusion. Called "alg:none + empty-key fallback" at :329. Version range is right, description is not.
In a skill whose whole job is teaching people which JWT flaws are real, a rejected CVE presented as live undermines the rest of the content. Worth a pass over every CVE in the PR.
scripts/agent.py:356 cannot run. forge_es256_confusion() calls public_key.public_bytes(Encoding.Raw, PublicFormat.UncompressedPoint), which raises ValueError — verified against cryptography 45.0.3, where Raw + UncompressedPoint raises and X962 + UncompressedPoint returns the expected 65 bytes. The formats list is an eager literal, so the entire ES256-confusion path raises on every call.
Smaller items:
- The rewritten description drops the "use when" clause, which fails the description linter. The version on
mainpasses. - This is CONFLICTING and reverts the 2026-08-02 description rewrite. Please rebase and keep main's description.
recover_ecdsa_private_key()hardcodeshashlib.sha256while the section advertises ES384/ES512, and never truncateszto the leftmostbitlen(n)bits.default_backend()is called in the second code fence while its import sits only in the first, so copy-pasting that block raisesNameError.- The rewrite deletes
CVE-2024-54150(cjwt). Worth restoring, andCVE-2024-33663(python-jose algorithm confusion) is a good addition while you are in there.
…coding, ECDSA hash selection) - Remove rejected CVE-2022-23529 (NVD: "DO NOT USE THIS CANDIDATE NUMBER") - Fix CVE-2015-9235 mislabels: NVD record is jsonwebtoken < 4.2.2 RS/ES->HS key confusion, not node-jws alg:none nor PyJWT empty-key behaviour - Fix CVE-2017-11424 description: PyJWT <= 1.5.0 PKCS#1 PEM detection bypass enabling key confusion - Restore CVE-2024-54150 (cjwt < 2.3.0) and add CVE-2024-33663 (python-jose <= 3.3.0 algorithm confusion) - Restore main's activation-rubric description (2026-08-02 rewrite), resolving the conflict flagged in review - forge_es256_confusion(): Encoding.Raw + UncompressedPoint raises ValueError in current cryptography releases; use Encoding.X962, which returns the expected 65-byte uncompressed point - recover_ecdsa_private_key(): select hash and curve order from the alg header (ES256/ES384/ES512) instead of hardcoding SHA-256/P-256, and truncate z to the leftmost bitlen(n) bits per FIPS 186-4 - advanced-attacks.md: add missing default_backend import in the recovery code block so it runs standalone; document z truncation
6472af0 to
a1e1f76
Compare
|
Thanks for the thorough review — all items are addressed in a1e1f76, and the branch is now rebased onto current CVE citations — every CVE now matches its NVD record:
Smaller items:
Note on CI: the check on the new head shows |
mukul975
left a comment
There was a problem hiding this comment.
Thanks for a thorough revision — I checked every item against the file at a1e1f76d rather than the summary, and all nine things I raised last round are genuinely fixed.
CVE-2022-23529 is gone. Zero occurrences across all seven files, and I did a second loose pass for a bare 23529, for GHSA/PYSEC/Snyk ids, and for vuln-DB URLs in case it had been re-cited in another form. Nothing. That was the one I cared about most — NVD has it as Rejected ("The issue is not a vulnerability"), and presenting it as live guidance is the worst failure mode for a skill whose job is telling people which JWT flaws are real. CVE-2015-9235 and CVE-2017-11424 are now correct, single-occurrence, and their bounds match NVD and OSV exactly. CVE-2024-54150 is back and accurate — its NVD status reads Deferred, which is an enrichment-backlog state and not a rejection, and GHSA-9h24-7qp5-gp82 is not withdrawn. CVE-2024-33663 is a good addition and checks out.
The ES256 path is alive again. agent.py:356-357 uses Encoding.X962 with PublicFormat.UncompressedPoint, and Encoding.Raw appears nowhere in the skill any more. I confirmed against cryptography 45.0.3 that all four entries in the formats literal are legal for an EC key, so the eager list evaluates cleanly and the function actually runs.
The ECDSA recovery is correct, and you fixed it the right way. agent.py:386-393 selects the hash from the token's own alg header instead of swapping in one more constant, and :450-455 implements the FIPS 186-4 truncation properly — excess = len(digest)*8 - n.bit_length(), shift only when positive, so SHA-512/P-521 correctly keeps the whole digest. I checked the three curve orders against an independent implementation rather than eyeballing them; they match. Generalising the dispatch is the version that stays correct, and having the identical fix land in advanced-attacks.md is exactly what I was hoping for after last time. The r1 != r2 guard is there and the half-split signature parse is right for RFC 7515 fixed-width R‖S.
The description is byte-identical to main's, "Use when" clause intact, and the 2026-08-02 rubric rewrite survives verbatim. That fix mattered more than it looks: this slug is grandfathered only under desc-has-negative-trigger, not under desc-has-use-when, so had the clause stayed dropped it would have been a hard new failure rather than an inherited one. No mass revert — zero overlap between your seven files and main's changed files since your base.
I rebuilt the merge locally and ran the full workflow: validate-skill.py 818/818, validate-agentskills.py 818/818, generate-index.py --check OK, lint-descriptions.py new failures 0, detect-collisions.py --max-unreviewed 55 exit 0 with this skill in no colliding pair, plus the two inline steps. Every number matches a main-only run, so nothing moves a baseline. No index.json needed — the description is unchanged.
Now the part nobody had looked at. Four of these files are new and I read them on their own terms, then went back through api-reference.md and scripts/agent.py because the same content lives there too. Before the list, two things I want to be fair about: I ran a per-fence undefined-name scan and my first read was that several fences were broken, then I ran the same scan against main's SKILL.md and all four of its fences have the identical shape. Fences continuing from the Step 0 preamble is this skill's existing convention, not something you introduced, and I'm not holding new files to a standard the file they were split from doesn't meet. Likewise attacker.com — main already ships it in SKILL.md and api-reference.md, so that's inherited.
Four things I'd like before merge:
1. A cracked binary secret silently forges a token that fails. bruteforce-sqli.md:40 returns secret.decode(errors='replace') and :61 re-encodes with found.encode(). Any non-UTF-8 secret becomes U+FFFD and re-encodes to different bytes, so a key you genuinely cracked yields a token that doesn't verify. Line 65 already warns "Secret may be binary." Return the bytes at 40, sign with found at 61, decode only for the print at 57. This turns a real finding into a false negative, which is the worst way for a pentest helper to fail.
2. to_bytes(256) on a caller-supplied key — in two files. header-injection.md:142 and agent.py:247, both inside forge_jwk_embedded_token(payload_dict, private_key, ...) where the key comes from the caller. A 4096-bit key raises OverflowError; a 1024-bit key gets 128 leading zero bytes, breaking RFC 7518's minimal-octet requirement for n and producing a JWK the server rejects. It's benign at header-injection.md:60 and agent.py:168 only because key_size=2048 is pinned two lines above each. (pn.n.bit_length() + 7) // 8 at both sites.
3. Two helper dependencies with no upstream definition anywhere. bruteforce-sqli.md uses ej() and b64url() at lines 60, 62, 86, 88, 103, 105; they're defined only in header-injection.md:16-17 and nowhere else in the skill. SKILL.md:100-101 routes HS256 targets straight to Step 7/8 without ever passing through header-injection.md, so that reader has genuinely never seen them. And header-injection.md itself uses json at :17, base64 at :16, requests at :29 and serialization at :178 while importing none of them — its first fence is already broken, so every later fence inherits it. This is the only place the fence convention actually fails; a complete preamble in the first fence of each fixes it.
4. api-reference.md:142-146 uses a live company's domain as the victim. The JKU/X5U bypass catalog hardcodes target.com — https://target.com@attacker.com/jwks.json, https://TARGET.COM/jwks.json, three more. That's Target Corporation's real domain, in the victim slot of payloads someone will copy verbatim. Your own parallel catalog at header-injection.md:188-200 gets this right by deriving target_host from BASE_URL; please mirror it here. This is new in the PR — main's api-reference.md doesn't have it.
Should fix, but I won't hold the merge on them alone:
- Third-party paste services as attack infrastructure, in three places:
header-injection.md:70-89,api-reference.md:104, 118-119, andagent.py:182-201, which carries the identicalhost_jwks(). The API calls are accurate — the objection is that this makes two unrelated operators' servers the infrastructure for someone else's engagement, puts client-adjacent material on an unauthenticated public blob store with no deletion step, and leaves engagement evidence somewhere the tester can't reach. Only the public half goes up, so nothing is compromised. Option C in your own table at line 101 — ngrok plus a local server — is the better default. /api/flagas the general success oracle. Gone from SKILL.md, still inbruteforce-sqli.md:89, 107,header-injection.md:30, 124,recon.md:27,api-reference.md:31— and, most importantly, as the default parameter value ofjku_diagnosticatagent.py:208, so it's what runs unless the operator overrides it. SKILL.md already uses/users/methroughout.- The JKU status-code heuristic is stated as a conclusion, in
header-injection.md:36-48,api-reference.md:111-112andSKILL.md:314. No general JWT stack guarantees 500→fetched / 502→connection failed / 401→ignored; an ignoring server, a fetch-and-fail server and one that 400s on a malformed header can all answer 401. Your line 40 has the signal that generalises, and you already have the right shape inagent.py:208-234, which returns raw{status, time, body}with no interpretation layer. Demote the codes to "compare against a control request." - Two mapping-table rows.
PyJWT < 2.0.0 | RS256→HS256 key confusion | —understates the range — and I nearly let it through on the reasoning that 2.0.0 is wherealgorithmsbecame required. That's true and beside the point: CVE-2022-29217 runs 1.5.0→2.4.0 and its precondition is an app passingget_default_algorithms(), which a required argument does nothing to prevent. Suggested:| PyJWT >= 1.5.0, < 2.4.0 | Key confusion via non-blocklisted public key formats | CVE-2022-29217 | 3 |— same bound atadvanced-attacks.md:77, so both files. Andexpress-jwt (node) < 6.0.0 | alg:none bypass | —is mislabelled: there's exactly one advisory in existence for that package, CVE-2020-15084 with range[0, 6.0.0), so the bound can only have come from it, and it's thealgorithmsallowlist going unenforced withjwks-rsa, not alg:none. Suggested:| express-jwt (node) <= 5.3.3 | algorithms not enforced with jwks-rsa secret → algorithm confusion / auth bypass | CVE-2020-15084 | 3 |. recon.md:70-83.r.json()at 74 is unguarded, line 76 returns the whole response dict from a function documented as "obtain a valid token," and the retry at 81 is unbounded recursion around a blocking 600-second sleep.- No authorisation line in any of the five reference files, though SKILL.md has one at 60-69 and — the reason this is nearly free —
agent.pyalready carries it three times, at 9, 503 and 530. Since SKILL.md:72 has the agent read references on their own, one line each pointing back to the Legal Notice.
Smaller notes, take or leave: advanced-attacks.md:188 hardcodes SECP256R1() six lines below the function you just generalised to ES384/ES512 (the alg→curve map is already at line 66). The EC format table at 20-26 lists five and line 43 says "all 5" while the list at 44-53 has four — the missing x‖y form is a distinct HMAC key, so it's a missed vector, and api-reference.md:262-267 lists four, so the two references disagree. SKILL.md:161's "base64 body only" slice keeps the END line and should be [1:-2] — that off-by-one is inherited from main's line 198 and your version is an improvement, since main left it as a list of str that raises TypeError at hmac.new, but as it stands no variant tests the true body-only format. advanced-attacks.md:385 lists /proc/self/environ in "Predictable File Targets," which fails that table's own criterion — it's NUL-separated and not byte-predictable, and if you can read it you take the secret directly. §9d's two payloads use two different Jackson type-id conventions under one heading: line 295 uses @class while the trigger named above it, enableDefaultTyping(), defaults to WRAPPER_ARRAY — the form your next payload at 309 correctly uses; and I couldn't confirm from a primary source that target is the right setter for SimpleJndiBeanFactory, so please re-derive rather than take my word either way. bruteforce-sqli.md:82 omits the trailing space after -- that your own exploit at 99 includes, so the probe can false-negative on MySQL. Lines 51-53 load all of rockyou under a heading that says "small wordlists." "RS256-PSS" (advanced-attacks.md:268, api-reference.md:304) should be PS256. advanced-attacks.md:209-212 is right about the GCD but should mention that e has to be known or guessed. And 13 tags makes this the most-tagged skill in the repo — nothing enforces a maximum, but trimming would keep it in line.
Two of my own, not yours. api-reference.md:68 has hmac.new(public_key_bytes, f"{header}.{payload}", hashlib.sha256) — the message is a str, which raises TypeError, and .digest() is missing; and base64url is called at 66, 67, 69, 86 and 87 without being defined. Both are lines 36-39 of the file on main and the diff only moved them. Your agent.py:130 and SKILL.md:154 do the HMAC correctly. Fix them here if convenient or leave them for me; neither is holding this up. The attacker.com usage is the same story — if you clean it up here, note that main needs the same edit or it'll come straight back.
On the rebase, a correction to the record rather than a request. Your base predates the tooling batch, so tools/ on your branch has 4 files where main has 11 — lint-descriptions.py, detect-collisions.py, generate-index.py and the baselines simply aren't there. Three of the seven gate steps reference tools you've never had and couldn't have run locally. Nothing to fix: the workflow checks out refs/pull/111/merge with no explicit ref and picks up main's tooling, and I've verified the gates pass on that merge.
What happens next: fix the four numbered items above and I'll merge. CI has never actually run on this head — check-runs is 0 and the combined status is pending, which is where the UNSTABLE state comes from — so everything above is my local reproduction; I'll approve the workflow run so the real thing executes alongside your next push. Take or leave everything under "smaller notes." I did not run any of the code in this PR; every runtime claim above I checked by running my own equivalent calls.
…reuse, deserialization RCE, and full JKU closure
…coding, ECDSA hash selection) - Remove rejected CVE-2022-23529 (NVD: "DO NOT USE THIS CANDIDATE NUMBER") - Fix CVE-2015-9235 mislabels: NVD record is jsonwebtoken < 4.2.2 RS/ES->HS key confusion, not node-jws alg:none nor PyJWT empty-key behaviour - Fix CVE-2017-11424 description: PyJWT <= 1.5.0 PKCS#1 PEM detection bypass enabling key confusion - Restore CVE-2024-54150 (cjwt < 2.3.0) and add CVE-2024-33663 (python-jose <= 3.3.0 algorithm confusion) - Restore main's activation-rubric description (2026-08-02 rewrite), resolving the conflict flagged in review - forge_es256_confusion(): Encoding.Raw + UncompressedPoint raises ValueError in current cryptography releases; use Encoding.X962, which returns the expected 65-byte uncompressed point - recover_ecdsa_private_key(): select hash and curve order from the alg header (ES256/ES384/ES512) instead of hardcoding SHA-256/P-256, and truncate z to the leftmost bitlen(n) bits per FIPS 186-4 - advanced-attacks.md: add missing default_backend import in the recovery code block so it runs standalone; document z truncation
Blocking items: - brute_force_hs256 returns bytes (agent.py + bruteforce-sqli.md aligned): non-UTF-8 secrets re-sign correctly; decode only for display - replace to_bytes(256)/(3) with bit_length-derived lengths in JWK/JWKS encoding so caller-supplied keys of any size produce minimal-octet n/e (RFC 7518) instead of OverflowError or 128 leading zero bytes - complete preamble in the first fence of bruteforce-sqli.md and header-injection.md so later fences resolve imports/helpers - api-reference.md: derive bypass-catalog host from BASE_URL instead of hardcoding Target Corporation's real domain in the victim slot Also: - local-first JWKS hosting (ngrok) as the default in all three copies; third-party paste services kept but documented as discouraged - /api/flag -> /users/me everywhere including jku_diagnostic default - JKU status-code heuristic demoted to control-request comparison in SKILL.md, api-reference.md, header-injection.md - CVE table: PyJWT >= 1.5.0, < 2.4.0 (CVE-2022-29217) and express-jwt <= 5.3.3 (CVE-2020-15084) with NVD-verified bounds and mechanisms - recon.md: guard r.json(), return the token not the dict, bound the rate-limit retry recursion - authorization line in all five reference files - 5th EC key format (x||y without 0x04) in both references and agent; [1:-2] PEM body slice; PS256 not "RS256-PSS"; drop /proc/self/environ from file targets; JdbcRowSetImpl WRAPPER_ARRAY payload in api-reference.md; trailing space after "--" in SQLi probes; rockyou load note; sig2n e=65537 note; trim tags 13 -> 9 - api-reference.md Step 3 fence: encode the hmac message and call .digest(); define base64url before first use
Mirrors references/advanced-attacks.md 9a and api-reference.md: the x||y form without the 0x04 prefix is a distinct HMAC key, so the agent was missing a vector the references document.
a1e1f76 to
41957a7
Compare
|
All four blocking items are fixed at 41957a7, along with everything under "should fix" and the smaller notes. I also rebased onto 1b3f6b2 so the branch now carries main's tooling batch, and ran the full gate suite locally against this exact head: Blocking items
Should-fix items — all done
Smaller notes — all done
On the rebase record: correct, and now moot in one direction — I fetched and rebased onto 1b3f6b2, so the branch has the full 11-file tools/ and I ran the three gates I'd never had locally. My four commits touch only the seven skill files, zero overlap with main's changes since either base. As before I ran none of this against a live target — every runtime claim above is my own local equivalent call. This push should trigger the workflow; looking forward to seeing the real CI run alongside your approval. |
|
Thanks for another careful round — most of this landed, and it landed cleanly. Head reviewed: Fixed, checked against the files rather than the description:
I also checked the ECDSA nonce-reuse math rather than taking the revision on trust: CVE table — all six rows against NVD directly. jsonwebtoken Three things before merge, and the first is the same defect class as last round in the file that round did not touch. 1. Four Python blocks in
Each is a NameError on copy-paste. Extending each block's own import line closes it: I ran the same fence-by-fence check over the other five markdown files and they are clean — only operator-supplied runtime values remain unbound there, which is fine. 2. The same function, same docstring, same unconditional POST, is also live at 3. if r.status_code == 200 and '"success":true' in r.text:Why it matters more than its size suggests: the fix commit did edit this block — the request two lines above is now Worth folding in while you are there, none blocking:
On process, one correction to something I said last round: we have no CI running on PR branches here, so "all checks green" was never the right phrasing. What I actually ran, locally on the merged tree: Fix those three and I will merge. |
…-first JWKS, status-only JKU check)
|
All three blockers and every non-blocking item are fixed at The three blockers:
Non-blocking items, all in: Two things worth flagging honestly:
|
|
Third round checked, and I ran things rather than reading the diff. Blocker 2 is done. I patched Blocker 1 I have to take back, and it is mine, not yours. Your four import lines are there — advanced-attacks.md:35, :136, :365 and :422, note :365 and :422 rather than the :360 and :415 in your comment — and nothing was deleted to fake them; the only removals in that file are the four superseded imports and the two JNDI prose lines. But I should not have asked for it. These files are written as one continuous session and they say so: header-injection.md:18, bruteforce-sqli.md:35, api-reference.md:68, plus the provenance comments at header-injection.md:22 and bruteforce-sqli.md:42. I wrote a module-level simulator that runs each file's fences in document order and SKILL.md comes back completely clean — all fifteen of its flagged fences resolve. My checker measures per-fence self-containment, which is not the standard these documents set. So nothing more is owed there. If you want the tidy-up: advanced-attacks.md:116 uses That checker also has a blind spot that cost me something real. It binds The thing that worries me most is not an import. Then the library and tool claims. I checked these against source rather than memory. bruteforce-sqli.md:15 says hashcat 16500 auto-detects from the alg header; Smaller things worth fixing while you are in there. header-injection.md:5-6 prescribes running 5d first, but 5d needs On gates: I ran all five locally at 08f867b plus the two CI-only steps — 818/818 validate-skill, 818/818 agentskills-strict, index up to date, zero new lint failures, collisions unchanged at 56 pairs against a cap of 55 unreviewed. What they do not cover is almost everything above: they read the SKILL.md frontmatter and its line count, which is seven of the 2,204 lines this PR adds, and nothing opens One non-blocking thing: the frontmatter description at SKILL.md:3-8 is unchanged from v1 and still describes only RS256 to HS256, alg:none and header injection, while the body now covers ES256, secret brute-force, kid SQLi, sig2n and deserialisation. It is the only text an agent sees when deciding whether to load the skill. I tested widening it — it lowers this skill's collision scores rather than raising them and drops it out of the lint baseline, so it is safe; just run Next step: fix the ECDSA verification (agent.py:528 and advanced-attacks.md:189, plus the wording at SKILL.md:278/:286), bind |
…very, sourcing corrections) Blocking: - recover_ecdsa_private_key (agent.py + advanced-attacks.md 9b): try all four low-s sign combinations and return a candidate only when it verifies — (k*G).x mod n == r, plus d*G == Q against a new --public-key input. A low-s-normalised pair previously returned a silently wrong key with status RECOVERED; an unverified pair is now reported unusable. - header-injection.md 5c: bind jwks_url to the URL the JWKS is served from (not host_jwks()'s local path) before the forging loop - sourcing corrections: hashcat 16500 picks its kernel from signature length, not the alg header, so an ES256 token is silently cracked as HS512 (bruteforce-sqli.md); jwt_tool -X i embeds a jwk header, jku spoofing is -X s -ju (api-reference.md); export_key() is PyCryptodome SPKI — the PKCS#1 row uses public_bytes(PEM, PKCS1) (api-reference.md); Java JJWT and go-jose are not vulnerable to algorithm confusion (SKILL.md rows dropped, negative note added); PyJWT never reads jwk/jku/x5u headers — dropped, node-jose/CVE-2018-0114 kept where accurate (header-injection.md) Also: - agent.py: report write moved into try/finally so malformed-token branches still produce the report; full tokens stored in the report (stdout lines stay truncated); --forge-jku rejects filesystem paths; PEM body slice strip()s first so a PEM without a trailing newline keeps its last base64 line (SKILL.md + api-reference.md same idiom) - SKILL.md: r described as the x-coordinate of k*G, not the nonce; --host-jwks output documented as a local path; description widened to cover the body with a negative trigger — index.json regenerated and the lint baseline shrunk by one
|
Fourth-round items are all in at d4ccf42: the ECDSA verification fix, the ECDSA recovery — the silently-wrong-key bug
SKILL.md's 9b table row and prose, and §9b, now describe r as the x-coordinate of the nonce point k·G — with the k/−k caveat — not "the nonce". jwks_url at header-injection.md §5c Bound to the URL the JWKS is actually served from ( The six sourcing corrections
The separate-pass items, included
Description Widened as you tested: ES256 confusion, HMAC brute-force, kid SQLi/traversal, sig2n, nonce reuse, deserialisation, with the negative trigger. The skill's collision scores dropped and it left the lint baseline (980 → 979, a shrink); index.json is regenerated in the same commit. On CI: understood that nothing has actually executed — the three runs are fork-PR action_required with zero jobs. The numbers above are the same gates the workflow would run, at this head; the workflow approval is still needed for them to count on GitHub. |
|
Fourth round checked. Every one of your six claims held up when I verified it independently, and I want to say that plainly before anything else, because the last two rounds each contained a self-audit that did not survive checking. This one did. The ECDSA fix is correct, and I proved my test could see the old bug before trusting the new result. I rebuilt the P-256 rig from scratch rather than re-run yours, pointed it at Two things I specifically went looking for came back clean. The new verification introduces no false negatives — And the two copies are genuinely in sync — the first time in four rounds. I extracted the I am still blocking, on two defects that predate this round and that neither of us has been looking at. Both are silent false negatives in 1. I signed three tokens with Exit 0, no warning, and the report records What makes this round the right time to fix it: 2. Running On the sourcing corrections: all six are confirmed fixed. hashcat 16500 really does branch on Two caveats on that, both about scope rather than substance. The JJWT note is unbounded, and the While you were in that table, four rows next to the ones you fixed are also wrong. I checked these against source because the go-jose and JJWT drops made me want to know what else was sitting there unsupported:
Smaller things. Two corrections to my own last comment. I wrote "collisions unchanged at 56 pairs against a cap of 55 unreviewed". The gate sits at exactly 55, which is the cap, and it sits there on main too — so this PR is collision-neutral, not collision-improving, and "exit 0 under the 55 cap" reads as more headroom than exists. Worth knowing that editing this one description shifted corpus IDF weights and moved 147 unrelated pairs, with 14 now within 0.02 of the cutoff; whoever next touches this frontmatter needs to re-run On gates and merge order: I ran all five locally on your branch merged into current main and they pass, but they read the frontmatter and a line count — seven lines of the 2,200 this PR touches — and nothing in them opens Next step: fix the two blockers — pass the algorithm through to the brute forcer, and reuse one keypair across |
Enhancement: JWT Algorithm Confusion Attack Skill
This PR significantly enhances the existing
exploiting-jwt-algorithm-confusion-attackskill from v1.0.0 to v2.0.0, adding 5 new attack vectors, a full reconnaissance phase, executable helper scripts, and deep-dive reference files.What's New
Files Changed
Compliance