Hashtag Web3 Logo

Critical Security Mistakes ZK Engineers Make

ZK circuits are unforgiving. A single missing constraint can allow provers to generate valid proofs for false statements. Learn from these critical mistakes.

For: zk engineerUpdated: March 13, 2026

Constraint Mistakes

Errors in circuit constraints.

critical

Signals that do not appear in any constraint let provers choose arbitrary values. This breaks the entire proof.

What happens: Prover can generate valid proofs for any output regardless of actual inputs.

Fix: Audit every signal. Each must appear in at least one constraint or be derived from constrained values.

critical

Treating a signal as boolean without constraining it to 0 or 1. Field elements have many other values.

What happens: Prover can use non-boolean values, breaking conditional logic.

Fix: Always add `signal * (signal - 1) === 0` for any boolean signal.

high

Array lookups where the index is not constrained to valid range.

What happens: Out-of-bounds access can leak information or cause unexpected behavior.

Fix: Add range checks for all array indices.

critical

Not constraining every step of Merkle path or getting left/right ordering wrong.

What happens: Invalid proofs accepted. Non-existent leaves proven to exist.

Fix: Verify each hash step. Test with known roots.

Arithmetic Mistakes

Finite field arithmetic errors.

critical

Assuming arithmetic works like integers. Field arithmetic wraps at the modulus.

What happens: Large numbers wrap to small numbers. Comparisons break. Security assumptions fail.

Fix: Add range checks. Be explicit about field size assumptions.

high

Not checking that denominators are non-zero before division.

What happens: Undefined behavior. Prover might be able to exploit edge cases.

Fix: Constrain denominators to be non-zero.

high

Field elements have two square roots. Not specifying which one is expected.

What happens: Prover can use either root, potentially breaking logic.

Fix: Constrain which square root by adding sign or range constraints.

high

Decomposing to bits but not constraining that bits reconstruct to original value.

What happens: Bits do not represent the actual value. Proofs become meaningless.

Fix: Always add reconstruction constraint: sum of bits * powers of 2 == original.

Cryptographic Primitive Mistakes

Errors using hashes and signatures.

critical

Hash inputs that are not fully constrained allow hash manipulation.

What happens: Prover can adjust unconstrained inputs to produce desired hash.

Fix: Every hash input must be fully constrained by circuit logic.

critical

Verifying only part of a signature or not including the message.

What happens: Signature forgery. Proofs for unauthorized actions.

Fix: Complete signature verification including message binding.

critical

Nullifiers that can be computed multiple ways for the same underlying item.

What happens: Double-spending. Same asset used multiple times with different nullifiers.

Fix: Nullifier derivation must be deterministic and unique.

high

Not validating that public keys are valid points on the curve.

What happens: Invalid keys can cause signature verification to misbehave.

Fix: Validate all external curve points are on the correct curve and subgroup.

Setup and Verification Mistakes

Errors in proof system setup and verification.

critical

Using setup parameters generated by one party. That party can create fake proofs.

What happens: Setup generator can forge proofs for any statement.

Fix: Use multi-party ceremonies (Powers of Tau) for trusted setup.

critical

Using the same proving key for different circuits.

What happens: Proofs from one circuit might be valid for another, breaking security.

Fix: Each circuit requires its own setup. Never reuse keys.

critical

Public inputs ordered differently between prover and verifier.

What happens: Verification succeeds for wrong values. Proofs prove wrong things.

Fix: Strict public input ordering. Test prover/verifier integration.

high

Proofs that can be replayed to repeat an action.

What happens: Same proof used multiple times. Actions repeated unintentionally.

Fix: Include nonces, timestamps, or nullifiers in public inputs.

Application Integration Mistakes

Errors connecting ZK proofs to applications.

high

Proof proves something but does not specify what action it authorizes.

What happens: Proof generated for one action used to authorize another.

Fix: Include action identifier in public inputs.

critical

Accepting proofs without recording their nullifiers.

What happens: Same proof used repeatedly. Double-spending.

Fix: Store all spent nullifiers. Check before accepting proofs.

high

Accepting proofs from clients without validating the public inputs make sense.

What happens: Malicious clients submit proofs with manipulated public inputs.

Fix: Validate public inputs server-side independent of the proof.

Performance and Implementation Mistakes

Errors causing inefficiency or bugs in production.

medium

Using multiplications in constraints where additions suffice.

What happens: Proving time increases significantly. Higher costs.

Fix: Optimize constraint degree. Use linear constraints when possible.

medium

Witness computation without time limits can hang indefinitely.

What happens: Malicious inputs cause denial of service. Provers hang.

Fix: Timeout on witness generation. Validate input complexity.

high

Mixing big and little endian in bit operations.

What happens: Values computed incorrectly. Proofs verify wrong data.

Fix: Standardize endianness across all operations. Document clearly.

medium

Circuits that allocate based on input size without limits.

What happens: Large inputs crash prover. Denial of service.

Fix: Fixed maximum input sizes. Validate before circuit execution.

medium

Leaving console logs or debug constraints in deployed circuits.

What happens: Information leakage. Unnecessary constraint overhead.

Fix: Strip debug code for production builds. Code review.

critical

Test private keys or constants left in production code.

What happens: Anyone can use test keys to forge proofs.

Fix: Separate test and production configurations. CI/CD checks.

Testing and Auditing Mistakes

Errors in verification and quality assurance.

critical

Testing only valid proofs without testing rejection of invalid ones.

What happens: Invalid proofs might be accepted. Soundness broken.

Fix: Test malicious inputs. Fuzz testing. Adversarial tests.

high

Relying solely on manual review for critical circuits.

What happens: Subtle constraint bugs missed by human reviewers.

Fix: Use formal verification tools like ecne, Circomspect.

high

Not testing boundary values and special cases.

What happens: Edge case inputs break circuit logic.

Fix: Test min/max values. Zero values. Field boundary values.

medium

Assuming circuit behaves identically across Groth16, PLONK, etc.

What happens: Bugs appear only in specific proof system deployment.

Fix: Test with target proof system. Understand system differences.

high

Dismissing Circom or other compiler warnings as noise.

What happens: Warnings often indicate real constraint issues.

Fix: Zero-warning policy. Investigate all warnings.

More for zk engineer