fix(stark): reject truncated deep_poly_openings instead of panicking#783
Merged
Conversation
reconstruct_deep_composition_poly_evaluations_for_all_queries indexes deep_poly_openings[i] for every FRI query index (0..fri_number_of_queries), but that Vec's length is never pinned — the only length guard in the verify path checks the separate query_list field. A malicious proof that keeps query_list intact but truncates deep_poly_openings makes the verifier panic with an out-of-bounds index instead of returning false (verifier DoS). Add a length guard at the top of the reconstruct helper (it already returns Option, so None cleanly rejects), mirroring the existing query_list guard. Add a negative test that truncates deep_poly_openings and asserts the verifier rejects without panicking.
diegokingston
approved these changes
Jul 6, 2026
ColoCarletti
approved these changes
Jul 6, 2026
jotabulacios
approved these changes
Jul 6, 2026
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.
Summary
The STARK verifier panics with an out-of-bounds index (rather than returning
false) when handed a malformed proof whosedeep_poly_openingsVec is shorter than the FRI query count. This is a verifier-DoS on malicious input.reconstruct_deep_composition_poly_evaluations_for_all_queriesindexesproof.deep_poly_openings[i]for everyi in 0..fri_number_of_queries, but that Vec's length is never checked. The only length guard in the verify path (proof.query_list.len() < fri_number_of_queries) validates a different field. A prover that keepsquery_listat full length but truncatesdeep_poly_openingssails through Fiat-Shamir replay, grinding, and step 2, then triggersindex out of boundsatverifier.rs:552.Fix
Add a length guard at the top of the reconstruct helper (it already returns
Option, soNonecleanly rejects), mirroring the existingquery_listguard. Extra entries stay harmless (never indexed), matching the<convention of that guard.Test
test_verify_rejects_truncated_deep_poly_openingsbuilds a valid proof, drops one opening, and asserts the verifier returnsfalsewithout panicking. Verified to have teeth: it panics atverifier.rs:552(index out of bounds: the len is 2 but the index is 2) against the unpatched verifier, and passes with the guard. Fullsmall_trace_testsmodule green;cargo fmt --checkandclippy -p starkclean.Context
Found while reviewing #729 (FRI early termination). The bug is pre-existing on
main, independent of that PR, so it is fixed here as a standalone hotfix rather than bundled into the feature branch. #729 adds structural length checks for exactly this class of untrusted-Vec-length bug on sibling fields; this closes the remaining one ondeep_poly_openings.