SNARKeling Treasure Hunt

First Flight #59
Beginner FriendlyGameFiFoundry
100 EXP
Submission Details
Impact: high
Likelihood: high

Treasure Secrets Stored as Plaintext Comments in Deployment Script

Author Revealed upon completion

Root + Impact

Description

  • The entire security model rests on participants physically finding a treasure and learning its secret. The ZK circuit exists precisely to prove knowledge of this secret without revealing it.

  • The deployment script hardcodes all 10 treasure secrets in a plaintext comment block that will be committed to version control and compiled into bytecode metadata.

// Secret Treasures for the snorkeling hunt (not revealed to the public):
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
@>// Treasures' hashes (revealed to the public, used as public inputs for the proof generation):
// 1505662313093145631275418581390771847921541863527840230091007112166041775502,
// -7876059170207639417138377068663245559360606207000570753582208706879316183353,
// -5602859741022561807370900516277986970516538128871954257532197637239594541050,
// 2256689276847399345359792277406644462014723416398290212952821205940959307205,
// 10311210168613568792124008431580767227982446451742366771285792060556636004770,
// -5697637861416433807484703347699404695743570043365849280798663758395067508,
// -2009295789879562882359281321158573810642695913475210803991480097462832104806,
// 8931814952839857299896840311953754931787080333405300398787637512717059406908,
// -4417726114039171734934559783368726413190541565291523767661452385022043124552,
// -961435057317293580094826482786572873533235701183329831124091847635547871092
// Note: The TreasureHunt contract requires funding at deployment, so we send 100 ETH

Risk

Likelihood:

  • Deployment scripts are routinely pushed to public GitHub repositories.

  • Even in a private repo, compiled contract bytecode embeds the IPFS/Swarm hash of the full source metadata, from which comments are recoverable.

  • Secrets 1 through 10 are trivially guessable by brute force regardless of whether the file is public.

Impact:

  • Any party who reads the script (or brute-forces the small secret space) can generate valid ZK proofs for all 10 treasures without ever visiting the hunt locations, claiming all 100 ETH before any legitimate finder can act.


The physical treasure hunt is rendered meaningless; the protocol's core value proposition is destroyed.

Proof of Concept

Off-chain attacker reads Deploy_s.sol and iterates over secrets 1-10

for (let secret of [1,2,3,4,5,6,7,8,9,10]) {
const proof = await generateProof(secret, recipientAddress); // valid ZK proof
await hunt.claim(proof, treasureHashes[secret-1], recipientAddress);
}
// All 100 ETH drained without physical participatioz.

Recommended Mitigation

Never store secrets in source code, comments, or version-controlled files. Generate secrets from a secure off-chain key management system (HSM, encrypted vault, etc.) and destroy them after their Pedersen hashes are committed to the circuit.

  • Use cryptographically random 32-byte secrets (e.g., cast keccak "$(openssl rand -hex 32)") rather than sequential integers.

  • Add a .gitignore rule that excludes any file containing raw secrets from version control.

  • Audit all metadata compilation outputs to ensure secret material is not embedded in bytecode CBOR/IPFS metadata.

- remove this code
+ add this code

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!