Skip to content

Bound untrusted decode paths against allocation DoS - #2

Open
mellowcroc wants to merge 1 commit into
audit/ed25519-key-validationfrom
harden/untrusted-decode-dos
Open

Bound untrusted decode paths against allocation DoS#2
mellowcroc wants to merge 1 commit into
audit/ed25519-key-validationfrom
harden/untrusted-decode-dos

Conversation

@mellowcroc

@mellowcroc mellowcroc commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Four consumer paths decoded ceremony-derived artifacts before checking the
length/count fields that drive allocation, letting a hostile or corrupt input
exhaust memory or panic — an unrecoverable throw on the native verifier, a
module abort on wasm.

  • prover.UnmarshalProof — preflight the BSB22 commitment-count prefix and
    the exact encoded length before gnark-crypto runs make([]G1Affine, count).
    Closes a remote, unauthenticated OOM on the verifier HTTP API (a ~200-byte
    body with a 0xFFFFFFFF count requested ~412 GB).
  • wasm-prover fetchCCS — bound the decoded CCS to its signed size
    (io.LimitReader), cap the zstd decoder window (WithDecoderMaxMemory, was
    64 GiB default), and recover() the decode so a hostile length prefix errors
    instead of aborting the module.
  • proofassets.ValidatePKIndexAllocations — bound NbWires,
    NbInfinityA/B, and NbCommitmentKeys against the signed FileSize and
    section geometry. Applied on the full-index paths (ReadPKIndex,
    streampk.ValidateIndex); the manifest digest covers only geometry, so the
    counters were otherwise free.
  • streampk domain decode — validate the FFT cardinality is canonical
    (power-of-two with a real generator, bounding it to the field's 2-adicity)
    before precomputing twiddles, so a hostile 2^32 cardinality is rejected
    before the ~274 GB allocation.

Adds regression tests for the proof and PK-index paths.

Note: this branch is stacked on audit/ed25519-key-validation (that branch's
on-curve commit already modifies keysource.go). Against main this PR's diff
therefore also includes the audit series; retarget the base to
audit/ed25519-key-validation, or merge that PR first, for a clean diff.

@mellowcroc
mellowcroc changed the base branch from main to audit/ed25519-key-validation August 13, 2026 09:47
Four consumer paths decoded ceremony-derived artifacts before checking the
length/count fields that drive allocation, letting a hostile or corrupt input
exhaust memory or panic (unrecoverable throw on the native verifier, module
abort on wasm):

- prover.UnmarshalProof: preflight the BSB22 commitment-count prefix and the
  exact encoded length before gnark-crypto runs make([]G1Affine, count). Closes
  a remote unauthenticated OOM on the verifier HTTP API.
- wasm-prover fetchCCS: bound the decoded CCS to its signed size, cap the zstd
  decoder window, and recover() the decode so a hostile length prefix errors
  instead of aborting the module.
- proofassets.ValidatePKIndexAllocations: bound NbWires, NbInfinityA/B, and
  NbCommitmentKeys against the signed FileSize and section geometry. Applied on
  the full-index paths (ReadPKIndex, streampk.ValidateIndex); the manifest
  digest covers only geometry, so the counters were otherwise free.
- streampk domain decode: validate the FFT cardinality is canonical before
  precomputing twiddles, so a hostile 2^32 cardinality is rejected before the
  ~274 GB allocation.

Adds regression tests for the proof and PK-index paths.
@mellowcroc
mellowcroc force-pushed the audit/ed25519-key-validation branch from 4164355 to dbbfb84 Compare August 13, 2026 09:48
@mellowcroc
mellowcroc force-pushed the harden/untrusted-decode-dos branch from 96daa63 to 56f410e Compare August 13, 2026 09:48
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.

1 participant