P3.34: ATO packet evidence index stale + exploit_id join key resolves to nothing - #75
Merged
Merged
Conversation
…rding (#68) evals/recordings/dos-unbounded-chat-message-length/ (VULN-0004's own live evidence) is not referenced anywhere in docs/ATO_EVIDENCE_PACKET.md §5.2, even though :29 points a reader there for VULN-0004. Derived from the filesystem so it self-updates as recordings/reports are added.
…oin key honestly (#68) Part A: §5.2 now names all five evals/recordings/ directories and all four docs/vuln_reports/ reports. Adds VULN-0004's own dedicated paragraph (1 draw, its own recording) and separates it clearly from the dismissed dos-overlong-query-max-query-chars probe (also 1 draw, not the same evidence, never filed a report). Fixes the "fourth recorded set" undercount (five exist) and the acceptance-check citation list. Part B (option 2): redteam/agents/documentation.py's docstring claimed exploit_id resolves "in the exploit DB", but no report-builder in this repo ever persists ExploitDB to disk (all use DocumentationAgent(reports_dir= None); ExploitDB defaults to :memory:). Softened the docstring to state the join key is in-process only and name the durable evidence that actually exists: evals/recordings/<probe>/ and the filed docs/vuln_reports/<id>.json. Chose this over committing an exploit-DB export because the durable evidence already exists and is already cited elsewhere in this repo; inventing a new export artifact for four static records would be a heavier, redundant fix for a docs-scoped issue. Extends tests/test_ato_evidence_index.py with a regression guard for the join-key claim.
…ests (#68) tests/test_ato_evidence_index.py adds 3 tests, moving the suite from 340/234 (with-sibling/CI) to 343/237. tests/test_doc_test_counts.py enforces every documented count claim stays truthful -- updated every occurrence in ATO_EVIDENCE_PACKET.md and DEMO_SCRIPT.md.
…ckout guard §5.3's "the repo has since grown to 250 total with the sibling checkout present" was stale -- self-contradicting §5.1's 343/237 (a 106 test delta while §5.3 asserted a 13-test delta). Corrected to 343. This is the third phrasing of "N ... with the sibling checkout" to slip tests/test_doc_test_counts.py -- widen the guard with a fourth pattern (N total with the sibling checkout present) and prove it now catches the stale value (verified red against the reverted 250, green against 343). Refs #68
….py docstring The prior fix's replacement prose introduced two NEW false claims: that durable evidence is "named directly on each report" (no committed VULN-*.json contains "evals/recordings" or "recording" -- the schema forbids a recording_ref field, and the report-to-recording mapping lives only in ATO §5.2), and that observed/expected "already carry the repro steps a reader needs" (they carry Judge.detect()'s label/message, not an endpoint, payload, token, or case module). Rewrote the docstring to the true chain: durable evidence lives under evals/recordings/<probe>/, mapped from report to recording only in ATO §5.2, with the runnable repro being evals/cases/<case>.py plus the recording JSON. Extended tests/test_ato_evidence_index.py (Part C) to catch both claim shapes, plus a ground-truth check against the actual report files. Red-first: verified both new patterns match the old (pre-this-commit) docstring wording before the docstring was rewritten. The two added test functions shifted the live suite count from 343/237 to 345/239 (skip count unchanged at 106) -- cascaded that count through every "with the sibling checkout" claim in ATO_EVIDENCE_PACKET.md and DEMO_SCRIPT.md so test_doc_test_counts.py stays green. Refs #68
…RE.md §3(4)/§1's report-field list and §6's AI-use-disclosure table both listed "minimal repro" as a filed report field / independently-verified fact. vuln_report.schema.json is additionalProperties:false with no minimal_repro/recording_ref field -- minimal_repro exists only on ExploitRecord, which no report-builder ever persists to disk. This contradicted documentation.py's own module docstring section titled "Why the vuln_report contract has no minimal_repro/recording_ref". Corrected all three spots (prose summary, component list, AI-use table) to name only the real schema fields and point to the report + ATO §5.2 + recording chain instead. Refs #68
…04 scope, test docstring - ATO_EVIDENCE_PACKET.md: VULN-0004's label is not a top-level field -- match the correct observed-field form used at ~:189. - §5.2 heading said "the three ... plus VULN-0004" but the next sentence opened "All three are reproducible..." unscoped; now "All three criticals are reproducible...". - tests/test_ato_evidence_index.py docstring claimed §5.2 "never mentioned VULN-0004" on main -- false, it did (the "Re-verifying" paragraph). Reworded to the real defect: §5.2 named VULN-0004 without describing its evidence. Added a stronger co-occurrence test requiring each report ID to appear near an evals/recordings/ path in §5.2, not merely anywhere in the section; verified it would have failed against the pre-fix docs (VULN-0004 was 2597 chars from the nearest recording mention, window is 300). Test count moved to 346/240 (skip count unchanged) from this PR's added tests -- cascaded through every doc claim again. Refs #68
…fier check Part C's repro-steps guard duplicated Part B's "flag this claim unless a qualifying phrase sits nearby" window logic verbatim. Extracted _unqualified_claims() and had both tests call it. Behavior-preserving: re-verified red-first proof against the old docstring wording still fails, full suite still 346 passed.
…y phrasing count The module docstring said "a FOURTH phrasing" in one clause and "it is the third phrasing to slip this guard" in the next -- self-contradictory. Reworded: it's the third distinct "N ... with the sibling checkout" phrasing specifically (after "move it to N with..." and "N tests with..."), not counting the unrelated "N-test suite" heading pattern.
franciszver
added a commit
that referenced
this pull request
Jul 26, 2026
…, upstream filings, and kickoff-constraint gap (issue #59) Extends tests/test_release_notes.py red-first with the corrected facts, then rewrites docs/RELEASE_NOTES_v3.0.0.md to match: - #63 and #68 are CLOSED (P3.31/P3.34) -- rewrites the limitations section as gaps found and closed, not open, and adds the three new limitations P3.31 introduced (pending_human_triage_count is per-run not directory-wide, --approve's --db-path opt-out, --reports-dir requiring --db-path). - All four findings are now filed upstream (#167-#170); corrects the false "no upstream issue for VULN-0001/2/3" paragraph and notes #169/#170 as evidence against upstream #130's closure premise, without demanding a reopen. - Owns the kickoff-brief hard-constraint gap explicitly: intent (no shared context) is met; the parenthesised OS-process mechanism is not, per ARCHITECTURE.md and the ATO packet, both already public. - Corrects the stale "redteam.observability not in the forbidden import set" claim -- it now is (test_judge_agent.py), and adds the symmetric Red-Team-side AST scan. - Re-derives test counts post-rebase (405 with sibling / 299 in CI, 106 skipped) across RELEASE_NOTES/ATO_EVIDENCE_PACKET/DEMO_SCRIPT. Rebase note: docs/ATO_EVIDENCE_PACKET.md and docs/DEMO_SCRIPT.md conflicts were resolved by taking main's post-#74/#75/#76 versions wholesale (verified main's wording already supersedes this branch's pre-rebase edits to the same passages), then bumping only the test counts to the new post-rebase live total. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTi1zKDS1ajefLSmM9oL7E
franciszver
added a commit
that referenced
this pull request
Jul 26, 2026
… by the rebase judge.py's (case, response, attempt_id) triple was cited at judge.py:96-100,343 -- score()'s actual signature moved to 348-357 as other main PRs (#74/#75/#76) touched the file. campaign.py's try:-guarded component calls were cited at ...,436 for the documentation.file_report try: block -- it moved to 446. Both verified against the current file on disk before correcting; no other citation in the doc drifted (spot-checked judge.py:44-47, chat.py:570-594, the recording path, and the JSON-report field claims against the live tree -- all still accurate). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTi1zKDS1ajefLSmM9oL7E
franciszver
added a commit
that referenced
this pull request
Jul 26, 2026
…, upstream filings, and kickoff-constraint gap (issue #59) Extends tests/test_release_notes.py red-first with the corrected facts, then rewrites docs/RELEASE_NOTES_v3.0.0.md to match: - #63 and #68 are CLOSED (P3.31/P3.34) -- rewrites the limitations section as gaps found and closed, not open, and adds the three new limitations P3.31 introduced (pending_human_triage_count is per-run not directory-wide, --approve's --db-path opt-out, --reports-dir requiring --db-path). - All four findings are now filed upstream (#167-#170); corrects the false "no upstream issue for VULN-0001/2/3" paragraph and notes #169/#170 as evidence against upstream #130's closure premise, without demanding a reopen. - Owns the kickoff-brief hard-constraint gap explicitly: intent (no shared context) is met; the parenthesised OS-process mechanism is not, per ARCHITECTURE.md and the ATO packet, both already public. - Corrects the stale "redteam.observability not in the forbidden import set" claim -- it now is (test_judge_agent.py), and adds the symmetric Red-Team-side AST scan. - Re-derives test counts post-rebase (405 with sibling / 299 in CI, 106 skipped) across RELEASE_NOTES/ATO_EVIDENCE_PACKET/DEMO_SCRIPT. Rebase note: docs/ATO_EVIDENCE_PACKET.md and docs/DEMO_SCRIPT.md conflicts were resolved by taking main's post-#74/#75/#76 versions wholesale (verified main's wording already supersedes this branch's pre-rebase edits to the same passages), then bumping only the test counts to the new post-rebase live total. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTi1zKDS1ajefLSmM9oL7E
franciszver
added a commit
that referenced
this pull request
Jul 26, 2026
… by the rebase judge.py's (case, response, attempt_id) triple was cited at judge.py:96-100,343 -- score()'s actual signature moved to 348-357 as other main PRs (#74/#75/#76) touched the file. campaign.py's try:-guarded component calls were cited at ...,436 for the documentation.file_report try: block -- it moved to 446. Both verified against the current file on disk before correcting; no other citation in the doc drifted (spot-checked judge.py:44-47, chat.py:570-594, the recording path, and the JSON-report field claims against the live tree -- all still accurate). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTi1zKDS1ajefLSmM9oL7E
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #68
Part A —
docs/ATO_EVIDENCE_PACKET.md§5.2 dangling pointer:29cross-referenced §5.2 for VULN-0004, but §5.2 never mentioned it — a reader following that pointer landed on a paragraph describing a different, dismissed DoS recording (dos-overlong-query-max-query-chars, TRI-013) instead of VULN-0004's own evidence.Fixed §5.2 to:
evals/recordings/directories (not "a fourth recorded set exists" — verified by listing, there are five).EXP-0004, medium severity,evals/recordings/dos-unbounded-chat-message-length/— 1 draw (stated honestly, not the 3-draw sample size of the three criticals).dos-overlong-query-max-query-charsprobe (also 1 draw, not the 2 draws the issue brief guessed — verified by directory listing; it never produced a filed report).VULN-000{1,2,3}→VULN-000{1,2,3,4}).Part B —
exploit_idjoin keyredteam/agents/documentation.py's docstring claimed a report'sexploit_idis "the join key back to the fullExploitRecord... in the exploit DB." Verified there is no committed exploit DB:tools/build_vuln_reports.py,tools/load_test_replay.py, andtools/run_campaign.pyconstructExploitDB(":memory:");tools/build_vuln_report_p3_54.pydoesn't construct anExploitDBat all (its own comment: "there is no persistent DB to add to"). All four report-builders constructDocumentationAgent(reports_dir=None).ExploitDB's own default is:memory:.EXP-0001..EXP-0004resolve to nothing a reader can open.(Correction, cold-review round 2: the original version of this paragraph overstated the audit — it claimed every report-builder "constructs
ExploitDB(\":memory:\")", which is false forbuild_vuln_report_p3_54.py. The paragraph above is the corrected wording.)Chose option 2 (soften the docstring) over committing an exploit-DB export: the durable evidence a reader actually needs already exists under
evals/recordings/<probe>/, mapped from report to recording only viadocs/ATO_EVIDENCE_PACKET.md§5.2 (see round 2 below — the report itself does not, and cannot, carry that mapping or repro steps) — inventing a new export artifact for four static records would be a heavier, redundant fix for a docs-scoped issue.Red-first
tests/test_ato_evidence_index.py— derived from the filesystem (everyevals/recordings/dir, everydocs/vuln_reports/*.json), so it self-updates as recordings/reports are added. Failing before the fix:Also adds a regression guard for the Part B join-key claim (verified it would have failed against the pre-fix docstring).
Cold-review round 2 (issue #68)
FIX 1 (BLOCKER). Part B's own fix introduced two NEW false claims: that durable evidence is "named directly on each report" (no committed
VULN-*.jsoncontainsevals/recordingsorrecordingat all — the schema forbids arecording_reffield), and thatobserved/expected"already carry the repro steps a reader needs" (they carryJudge.detect()'s detection signal — a label/message string — not an endpoint, payload, token, or case module). Rewroteredteam/agents/documentation.py's docstring to the true chain: durable evidence lives underevals/recordings/<probe>/; the report-to-recording mapping lives only in ATO §5.2;observed/expectedcarry the detection signal, not repro steps; the runnable repro isevals/cases/<case>.pyplus the recording JSON. Extendedtests/test_ato_evidence_index.py(Part C) with two new regex guards plus a ground-truth check against the actual report files. Red-first: verified both new patterns match the old (pre-round-2) docstring wording before it was rewritten.FIX 2 (BLOCKER).
docs/ATO_EVIDENCE_PACKET.md§5.3 said "the repo has since grown to 250 total with the sibling checkout present" — stale (self-contradicted §5.1's 343/237 pair at the time). Corrected to the live count. Widenedtests/test_doc_test_counts.pywith a fourth pattern (N total with the sibling checkout present) — the third distinct "N ... with the sibling checkout" phrasing to slip this guard. Verified red against the stale value, green against the corrected one.FIX 3.
docs/ARCHITECTURE.mdlisted "minimal repro" as a filed-report field in three places (§1 prose summary, §3(4) component list, §6 AI-use-disclosure table).vuln_report.schema.jsonisadditionalProperties: falsewith nominimal_repro/recording_reffield —minimal_reproexists only onExploitRecord, never persisted — contradictingdocumentation.py's own docstring section on this exact point. Corrected all three spots to name only real schema fields and point to the report + ATO §5.2 + recording chain.One-liners.
label: "accepted_no_bound_observed"was presented as a top-level VULN-0004.json field; it's only insideobservedprose. Matched the correct form used at ~:189.tests/test_ato_evidence_index.pydocstring claimed §5.2 "never mentioned VULN-0004" onmain— false, it did (the "Re-verifying" paragraph, within §5.2's span). Reworded to the real defect (§5.2 named VULN-0004 without describing its evidence) and added a stronger co-occurrence test requiring each report ID to appear within 300 characters of anevals/recordings/path in §5.2, not merely anywhere in the section. Verified it would have failed against the pre-Part-A docs (VULN-0004 was 2597 characters from the nearest recording mention there).Declutter (inline gate). Folded a duplicated "flag this claim unless a qualifying/negating phrase sits nearby" window-check into a shared
_unqualified_claims()helper (Part B's join-key check and Part C's repro-steps check both needed it) — behavior-preserving, re-verified against the red-first proofs and full suite.Self-caught in deep-review: the
tests/test_doc_test_counts.pydocstring I wrote for FIX 2 was internally contradictory ("a FOURTH phrasing... it is the third phrasing to slip this guard"). Reworded to disambiguate — third within the "N ... with the sibling checkout" family specifically, not counting the unrelated heading pattern.Test count moved 343/237 → 346/240 across this round (5 test functions added net across Part C + the co-occurrence strengthening; skip count unchanged at 106) — cascaded through every "with the sibling checkout" / "N passed" claim in
ATO_EVIDENCE_PACKET.mdandDEMO_SCRIPT.md.Gates (inline, full diff, both rounds)
evals/cases//evals/recordings/filesystem contents.Suite
pytest tests/test_doc_test_counts.py -q→2 passed.pytest tests/ -q→346 passed(sibling Phase 2 checkout present locally).Evidence integrity
docs/vuln_reports/*.jsonuntouched across both rounds — sha256 verified identical before/after every commit on this branch (nomain()of any report-building tool was run against the real directory).What I found wrong in the issue brief / earlier PR description while verifying
dos-overlong-query-max-query-charshas 1 draw, not 2 as the issue brief guessed — confirmed byls evals/recordings/dos-overlong-query-max-query-chars/(onedraw1file +TRACE_RESOLUTION_NOTE.md). Documented the actual count.build_vuln_report_p3_54.pyconstructs anExploitDB; it doesn't). Corrected above.🤖 Generated with Claude Code
https://claude.ai/code/session_01TTi1zKDS1ajefLSmM9oL7E