Skip to content

security(reputation): prevent source-generation ABA replay - #191

Draft
seonghobae wants to merge 8 commits into
chatgpt/reputation-atomic-source-replacement-v1from
chatgpt/reputation-source-generation-replay-v1
Draft

security(reputation): prevent source-generation ABA replay#191
seonghobae wants to merge 8 commits into
chatgpt/reputation-atomic-source-replacement-v1from
chatgpt/reputation-source-generation-replay-v1

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Refs #190 and #192. Draft child of #189.

Exact parent/current base remains #189@7f715a843236bcb79452fc1b3c84d50f34da9981.

Original RED and bounded lifecycle implementation

The first production-unchanged hostile fixture was established at ce56ee0645c046a4572e97cf9cc4889945205b59. Hosted CI 34165964131, job 101876937399, completed checkout, Rust setup, and formatting, then failed because SourceGenerationLifecycleCursorV1, SourceGenerationLifecycleErrorV1, and EvidenceSnapshotV1::replace_source_with_lifecycle did not yet exist.

1504a1424f737016461dc0f84db2659c027649a9 added a bounded pure-Rust current-generation lifecycle cursor and atomic immutable snapshot+cursor return value. CI then exposed a dead-module integration defect; f9b00db81790b335f9f06ce4d48770ff8630f0c2 declared/re-exported the module. 3aac5304773652096a5895ec95b60fcf858005af added stale ordinal, collision, schema/text/time, invalid retained-cursor, and missing/spurious cursor-membership cases. Formatting-only c30a9028c69011b6884825841f761f12916f5bfc and 9d42b7da750570a970785242b7f26072e89a558e applied hosted rustfmt output. Exact 9d42... then passed CI 34168771438 and Fuzz 34168771365.

That GREEN proved only single-hop/current-cursor invariants. Fresh exact-source review found that it did not satisfy the issue-level historical ABA claim.

Multi-hop ABA RED — current exact state

Current exact source head is ed6ba763b7feeb9a4ac67653776619c34783023e. It is a non-force, test-only child of 9d42...; comparison is ahead 1 / behind 0 and changes only crates/wardnet-reputation-core/tests/source_generation_lifecycle.rs (+38/-0). Production source is unchanged.

The added hostile sequence is:

  1. retain generation-8 @ ordinal 8;
  2. validly advance to generation-9 @ ordinal 9;
  3. replay the historically consumed opaque token generation-8 at authenticated ordinal 10;
  4. require fail-closed ReusedSourceGeneration.

Hosted CI 34172081051, rust job 101894179030, acquired GitHub-hosted runner 1001761240. Checkout/toolchain and cargo fmt --check succeeded. cargo test --locked --workspace then failed exactly in source_generation_lifecycle_rejects_aba_token_rebinding_at_a_newer_ordinal: the implementation returned Ok(SourceReplacementTransitionV1 { ... source_generation: "generation-8", source_generation_ordinal: 10 ... }) while the test requires Err(ReusedSourceGeneration). Nine other lifecycle tests passed. Clippy was skipped after the semantic test failure.

Exact Fuzz 34172081085, job 101894179222, is terminal SUCCESS on the same unchanged ed6ba763b7feeb9a4ac67653776619c34783023e. GitHub-hosted runner 1001761232 completed checkout/toolchain/cargo-fuzz setup and every bounded fuzz target; no crash artifact was produced. This does not convert the semantic CI RED into GREEN.

This is the current authoritative RED. The predecessor 9d42... successes must not be represented as exact-current GREEN.

Root cause and causal successor

SourceGenerationLifecycleCursorV1 retains only the currently represented generation token/ordinal. After 8@8 -> 9@9, historical binding 8@8 is forgotten, so a current-only cursor cannot prove that 8@10 is a replay. A fixed-size recent-token cache would merely postpone ABA acceptance or impose an arbitrary source lifetime and is not an acceptable commercial security invariant.

#192 now owns the durable causal repair under #80: tenant-scoped PostgreSQL uniqueness must bind both (source_id, source_generation) and (source_id, source_generation_ordinal) and commit those bindings atomically with producer lifecycle state, evidence snapshot, completeness/pagination proof, and last-known-good publication. Real PostgreSQL tests must cover multi-hop ABA, concurrent writers, crash/retry/idempotency, RLS/pool context, migrations, and restore. #140 Runtime Configuration is the prerequisite foundation before reconstructing #80; stale mixed #95 is evidence only and must not be imported wholesale.

This PR deliberately remains Draft/RED until that durable history authority exists or another bounded implementation can prove the full invariant without weakening it. Do not delete the hostile test, cap history to manufacture GREEN, or claim a current-only cursor is global replay authority.

Boundary

The contract remains Wardnet security-evidence admission only. It performs no feed fetching, HTTP/304 interpretation, destination URL/DNS/peer/redirect/proxy/TLS/resource authorization, Context Graph/EA mutation, quarantine execution, LLM/provider routing, or AppGuardrail analysis. Authenticated normalized ordinal derivation remains source-adapter authority. Durable reputation history remains Wardnet-owned state under #80/#192.

No predecessor-result transfer, self/model approval, routine administrator bypass, force push/destructive rebase, mutable foreign dependency, source copy, cross-service SQL, or gate weakening.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae changed the title test(reputation): prevent source-generation ABA replay security(reputation): prevent source-generation ABA replay Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: high High-priority or P1 work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant