Skip to content

fix(drive): bind proof-verifier queries to trusted context#4166

Merged
QuantumExplorer merged 12 commits into
v4.1-devfrom
codex/fix-proof-context-binding
Jul 22, 2026
Merged

fix(drive): bind proof-verifier queries to trusted context#4166
QuantumExplorer merged 12 commits into
v4.1-devfrom
codex/fix-proof-context-binding

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

  • require vote proofs to bind a full serialized poll to its expected ID, contract, document type, index, and exact contested-index arity
  • reject WASM known-contract entries whose map key differs from the embedded contract ID
  • stop using unsigned response metadata to select epoch-dependent proof queries; ambiguous current-epoch requests now fail closed

This addresses security review findings DS-CAND-314, 368, and 374.

Compatibility

The two WASM vote-proof exports now require both an expected poll ID and the full serialized vote poll.

Proved epoch queries no longer derive their bound from unsigned metadata:

  • ExtendedEpochInfo::fetch_current (a descending epoch query with no explicit start) now fails closed with proved descending epoch queries require an explicit start epoch. There is no authenticated current-epoch marker to bound the query, so a node could otherwise cap the proof below the chain tip and pass off a stale epoch as current. Callers must fetch a specific epoch by explicit index until such a marker exists.
  • The proved evonode-proposed-epoch-blocks queries likewise require an explicit epoch.

A contested vote poll must now carry exactly as many index values as the index has properties; under-specified polls are rejected instead of silently resolving a partial path.

Validation

  • cargo check -p drive-proof-verifier --lib
  • cargo check -p wasm-drive-verify --lib
  • cargo test -p drive-proof-verifier --lib (242 passed)
  • cargo test -p drive --lib contenders_path_rejects_missing_index_values
  • cargo test -p wasm-drive-verify --lib (4 passed)
  • cargo test -p dash-sdk --test main fetch::epoch:: fetch::contested_resource_voters:: (7 passed) — realigned test_epoch_fetch_current and test_contested_resource_voters_for_identity_not_found to assert the new fail-closed behavior
  • cargo clippy -p drive -p drive-proof-verifier -p wasm-drive-verify --lib --no-deps -- -D warnings
  • cargo fmt --all
  • git diff --check

@github-actions github-actions Bot added this to the v4.1.0 milestone Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7c98848b-49bb-4c25-a1e9-477476974976

📥 Commits

Reviewing files that changed from the base of the PR and between 2b3e3fc and e97fcee.

📒 Files selected for processing (14)
  • .github/workflows/kotlin-sdk-build.yml
  • .github/workflows/tests-rs-workspace.yml
  • packages/rs-drive-proof-verifier/src/proof.rs
  • packages/rs-drive/src/drive/votes/paths.rs
  • packages/rs-sdk/tests/fetch/contested_resource_voters.rs
  • packages/rs-sdk/tests/fetch/epoch.rs
  • packages/rs-unified-sdk-jni/src/tx_decode.rs
  • packages/swift-sdk/build_ios.sh
  • packages/swift-sdk/run_tests.sh
  • packages/wasm-drive-verify/Cargo.toml
  • packages/wasm-drive-verify/src/state_transition/verify_state_transition_was_executed_with_proof.rs
  • packages/wasm-drive-verify/src/voting/mod.rs
  • packages/wasm-drive-verify/src/voting/verify_vote_poll_vote_state_proof.rs
  • packages/wasm-drive-verify/src/voting/verify_vote_poll_votes_proof.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-proof-context-binding

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.

@QuantumExplorer
QuantumExplorer marked this pull request as ready for review July 21, 2026 02:04
@thepastaclaw

thepastaclaw commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

🕓 Ready for review — 33 ahead in queue (commit e97fcee)
Queue position: 34/72 · 2 reviews active
ETA: start ~03:37 UTC · complete ~04:06 UTC (median 28m across 30 recent reviews; 2 slots)
Queued 18h 18m ago · Last checked: 2026-07-22 19:40 UTC

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.39216% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.46%. Comparing base (ce8aecb) to head (e97fcee).
⚠️ Report is 9 commits behind head on v4.1-dev.

Files with missing lines Patch % Lines
packages/rs-drive-proof-verifier/src/proof.rs 41.17% 10 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           v4.1-dev    #4166      +/-   ##
============================================
- Coverage     87.63%   87.46%   -0.18%     
============================================
  Files          2624     2651      +27     
  Lines        331678   334769    +3091     
============================================
+ Hits         290659   292795    +2136     
- Misses        41019    41974     +955     
Components Coverage Δ
dpp 88.44% <ø> (ø)
drive 86.13% <100.00%> (+<0.01%) ⬆️
drive-abci 89.58% <ø> (+0.01%) ⬆️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.90% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 49.79% <41.17%> (+0.12%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final validation — Codex + Sonnet

Verified the combined Codex checkpoint and all four Sonnet reviewer lanes at head b535feb against actual source. The PR correctly binds vote-poll proof verification to caller-supplied context and epoch selection to request-derived values instead of unsigned response metadata. The two FFI suggestion findings are independently confirmed: both functions insert a new required expected_vote_poll_id: &Uint8Array parameter mid-argument-list and reinterpret poll bytes as a serialized ContestedDocumentResourceVotePoll, while package.json remains at 4.0.0 and no in-repo JS/TS consumer exercises either export.

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (failed), gpt-5.6-sol — security-auditor (failed), gpt-5.6-sol — rust-quality (failed), gpt-5.6-sol — ffi-engineer (failed), gpt-5.6-sol — general (completed), gpt-5.6-sol — security-auditor (failed), gpt-5.6-sol — security-auditor (completed), gpt-5.6-sol — rust-quality (completed), gpt-5.6-sol — ffi-engineer (completed)
  • Verifier: claude-sonnet-5 — final-verifier
  • Sonnet reviewers: claude-sonnet-5 — general (failed), claude-sonnet-5 — general (failed), claude-sonnet-5 — security-auditor (failed), claude-sonnet-5 — security-auditor (failed), claude-sonnet-5 — rust-quality (failed), claude-sonnet-5 — rust-quality (failed), claude-sonnet-5 — ffi-engineer (failed), claude-sonnet-5 — ffi-engineer (failed), claude-sonnet-5 — general (failed), claude-sonnet-5 — general (completed), claude-sonnet-5 — security-auditor (completed), claude-sonnet-5 — rust-quality (completed), claude-sonnet-5 — ffi-engineer (completed), claude-sonnet-5 — rust-quality (completed), claude-sonnet-5 — ffi-engineer (completed)

🟡 2 suggestion(s)

2 additional finding(s) omitted (not in diff).

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/wasm-drive-verify/src/voting/verify_vote_poll_vote_state_proof.rs`:
- [SUGGESTION] packages/wasm-drive-verify/src/voting/verify_vote_poll_vote_state_proof.rs:38-49: wasm_bindgen export signature changed in a breaking, unversioned way
  `verify_vote_poll_vote_state_proof` (exported as `verifyVotePollVoteStateProof`) inserts a new required `expected_vote_poll_id: &Uint8Array` parameter between `index_name` and `contested_document_resource_vote_poll_bytes`. Since wasm-bindgen exports are called positionally from JS/TS, every existing caller's argument list shifts: the old vote-poll-identifier bytes now land in the `expected_vote_poll_id` slot, and `contested_document_resource_vote_poll_bytes` must now be a fully platform-serialized `ContestedDocumentResourceVotePoll` (via `ContestedDocumentResourceVotePoll::deserialize_from_bytes`) rather than a bare 32-byte `Identifier`. This is a legitimate, deliberate security fix, but it's a larger data-format change than the parameter diff suggests, and package.json for wasm-drive-verify is still at 4.0.0 with no changelog/migration note. No in-repo consumer exercises this export, so there's no compiled signal for downstream callers that the contract changed.

In `packages/wasm-drive-verify/src/voting/verify_vote_poll_votes_proof.rs`:
- [SUGGESTION] packages/wasm-drive-verify/src/voting/verify_vote_poll_votes_proof.rs:36-49: Same breaking positional-signature change as verify_vote_poll_vote_state_proof
  `verify_vote_poll_votes_proof` (exported as `verifyVotePollVotesProof`) has the same shape of change as its sibling: a new required `expected_vote_poll_id: &Uint8Array` parameter inserted before `contested_document_resource_vote_poll_bytes`, and that parameter's expected byte format switches from a raw Identifier to a platform-serialized `ContestedDocumentResourceVotePoll`. Same unversioned-breaking-change concern as the sibling function.

@QuantumExplorer QuantumExplorer changed the title fix(proof-verifier): bind queries to trusted context fix(drive): bind proof queries to trusted context Jul 21, 2026
…closed proof context

The proof-context hardening deliberately fails closed on two client requests
that previously leaned on unauthenticated inputs, but the SDK fetch tests still
asserted the old permissive behavior:

- test_epoch_fetch_current expected fetch_current (a descending epoch query with
  no explicit start) to succeed; it now returns the explicit-start rejection.
- test_contested_resource_voters_for_identity_not_found passed a single index
  value for the two-property parentNameAndLabel index; the arity guard now
  rejects the under-specified poll.

Update both tests to assert the new rejections so they document the intended
security behavior (DS-CAND-314 / DS-CAND-374).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer changed the title fix(drive): bind proof queries to trusted context fix(drive): bind proof-verifier queries to trusted context Jul 21, 2026

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed

@QuantumExplorer
QuantumExplorer merged commit a542cba into v4.1-dev Jul 22, 2026
26 checks passed
@QuantumExplorer
QuantumExplorer deleted the codex/fix-proof-context-binding branch July 22, 2026 04:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants