Mina o1js Security Review Skill
Use when
Use this skill when the user asks for an audit, security review, vulnerability assessment, threat model, hardening plan or code review for a Mina/o1js zkApp.
This skill is defensive. Review only user-owned or authorized code.
Shared references
If installed from the full package, shared resources live in ../mina-protocol-agent/references/. Load ../mina-protocol-agent/references/INDEX.md only when task cards, examples, templates, source links or deeper checklists are needed.
Compatibility gate
Before a version-sensitive claim, record the target network, active protocol era, exact o1js and signer versions, wallet/CLI versions, endpoints, and the origin of verification keys and proof caches. Load ../mina-protocol-agent/references/playbooks/NETWORK_ERA_AND_O1JS_COMPATIBILITY.md for Berkeley/Mesa and o1js 3 migration rules. If the era is unknown, label the guidance unverified rather than guessing from package or endpoint names.
Current high-risk review additions
Add these checks to every applicable audit:
- network era, signer era, transaction JSON, verification key, proof, and cache are mutually compatible;
- state/event/action/AccountUpdate limits are derived from the target era and boundary-tested;
- variable-length commitments use unambiguous length/domain binding;
TokenContract.deploy() permission behavior is verified from the pinned version and on-chain state;
- wallet submission is inspected after proving and before signing;
- submitted, included, archive-indexed, safe, and final are not conflated;
- delegated authority binds mission, agent, app/network, tools/data, budget, expiry, replay control, and receipts.
Load ../mina-protocol-agent/references/playbooks/TRANSACTION_LIFECYCLE_AND_WALLET_PREFLIGHT.md and ../mina-protocol-agent/references/playbooks/DELEGATED_AUTHORIZATION_AND_PRIVACY.md when those surfaces exist. Load ../mina-protocol-agent/references/playbooks/DEPLOYMENT_PROVENANCE_AND_REDEPLOY.md whenever verification keys, permissions, state layout, deployments, upgrades, key rotation, or runtime configuration are in scope.
Safety boundary
- Do not provide destructive exploitation against third-party systems.
- Do not exfiltrate secrets.
- If secrets appear in files, report minimal evidence and recommend immediate rotation.
- Do not ask the user to paste private keys, seed phrases or production secrets.
Review principle
Mina/o1js security bugs often happen when a developer believes a normal TypeScript check is part of the proof, or when an AccountUpdate/permission path allows something the proof logic did not intend.
Always separate:
Ordinary TS runtime check
Provable assertion
State precondition
Signature authorization
Permission authorization
Transaction/AccountUpdate structure
Frontend/backend trust assumption
Audit workflow
1. Scope capture
Collect or infer:
- repository and commit hash;
- o1js version and zkApp CLI version;
- deployed addresses if any;
- target network;
- in-scope files;
- roles: deployer, admin, user, prover, frontend, backend, relayer, oracle, issuer, auditor;
- assets at risk: MINA, custom tokens, credentials, votes, reputation, private data, verification keys;
- high-risk features: tokens, reducers/actions, custom AccountUpdates, recursion, Merkle state, credentials, external data.
2. Architecture map
Produce this before findings:
Contracts:
ZkPrograms:
State fields:
Methods and call graph:
Events/actions:
AccountUpdate tree per user flow:
Permissions and upgrade policy:
Frontend/prover/backend flow:
External dependencies:
3. Invariant list
Write project-specific invariants. Examples:
- only authorized users can update state;
- state transitions bind to the current on-chain state;
- every private witness is constrained to public input or on-chain commitment;
- nullifier can be used only once;
- token supply equals documented mint minus burn plus/minus pending operations;
- all token movements are approved by the intended token owner logic;
- every accepted action can be reduced without permanently bricking the contract;
- admin cannot silently replace verification key unless explicitly documented;
- private data does not appear in public inputs, events, actions, logs or analytics;
- frontend/backend cannot forge a proof or swap public inputs without detection.
4. Code review checklist
Provable constraints
- Security checks use
assertEquals, assertTrue, assertFalse, range assertions or equivalent provable constraints.
- No witness is accepted without being tied to a public root, hash, signature, commitment or state value.
- Conditional logic uses
Provable.if() correctly and avoids side effects inside branches.
- Fixed-size provable arrays are used where required.
Field modular arithmetic is not used where bounded integer behavior is required.
- Hashes include domain separation.
- Signatures bind all required fields: app id, chain/network id if needed, contract address, action id, nonce/nullifier, amount, recipient, expiry.
State and preconditions
- Security-critical state reads use
getAndRequireEquals() or requireEquals().
- Account and network preconditions are explicit for balances, nonce, timestamp, slot, delegate or token state where relevant.
- Stale state and concurrent user flows are handled.
AccountUpdates
- Every AccountUpdate has the intended account, tokenId, authorization and balance change.
- Child AccountUpdates cannot inherit unintended token powers.
mayUseToken and token ownership are understood and tested.
fundNewAccount, AccountUpdate.create, createSigned, approve, custom send/mint/burn flows are reviewed.
- Transaction shape is stable enough for security assumptions.
Permissions and upgrades
- Permission matrix is documented.
setVerificationKey and setPermissions are not left too loose.
- Least authority is applied.
- Upgrade path is either locked, proof-governed, multisig/timelock-governed or clearly documented as admin-trusted.
Actions/reducers
- Actions are public and not used for secret data.
- Reducer can process malformed or adversarial actions safely.
- Action type has canonical representation if needed.
- Queue growth, batching and griefing are considered.
- Reduction state cannot be permanently stuck by one bad action.
Privacy
- Public inputs, events, actions and state do not reveal private values accidentally.
- Backend and frontend do not log private witnesses.
- Nullifiers are domain-separated.
- Timing/IP/wallet metadata risks are documented when privacy claims are made.
Dependencies and devops
- o1js version is pinned.
- Deprecated APIs are flagged.
- Deployment scripts do not expose keys.
- CI does not print secrets or proofs containing sensitive auxiliary data.
- Frontend integrity and supply chain risks are considered.
Finding format
### [Severity] Title
Affected files:
Confidence: High / Medium / Low
Category:
Description:
Impact:
Why this happens in Mina/o1js:
Proof-of-concept or exploit sketch:
Recommended fix:
Regression test:
References:
Severity guide
- Critical: direct theft, arbitrary mint/burn, arbitrary state update, verification key replacement, permanent fund lock for high-value assets.
- High: unauthorized privileged action, replay of important operation, broken nullifier, severe privacy leak, reducer bricking.
- Medium: missing precondition with realistic race risk, incomplete supply invariant, centralization risk not documented, unsafe upgrade process.
- Low: weak docs, test gaps, non-critical leakage, maintainability issues.
- Informational: hardening suggestion or architectural note.
Required output
For every review, return:
- Scope and assumptions.
- Architecture map.
- Role model.
- Permission matrix.
- AccountUpdate map.
- Invariants.
- Findings.
- Test gaps.
- Deployment risks.
- Recommended next steps.
Red flags
get() without requireEquals() on state used in security logic.
Provable.witness() without assertions tying it to public data.
Field used as token amount without range/UInt wrapper.
- JS
if depending on provable values.
- Admin can set verification key by signature without disclosure.
- Token manager approves arbitrary child updates.
- Reducer assumes all actions are honest.
- Events/actions contain PII or secrets.
- Tests only cover happy path.
- README claims privacy but frontend sends raw credential to backend.
1---2name: mina-o1js-security-review3description: Use when auditing, threat modeling, hardening, or reviewing Mina o1js zkApps, circuits, AccountUpdates, permissions, custom tokens, frontend prover flows, privacy, or deployment security.4---56# Mina o1js Security Review Skill78## Use when910Use this skill when the user asks for an audit, security review, vulnerability assessment, threat model, hardening plan or code review for a Mina/o1js zkApp.1112This skill is defensive. Review only user-owned or authorized code.1314## Shared references1516If installed from the full package, shared resources live in `../mina-protocol-agent/references/`. Load `../mina-protocol-agent/references/INDEX.md` only when task cards, examples, templates, source links or deeper checklists are needed.1718## Compatibility gate1920Before a version-sensitive claim, record the target network, active protocol era, exact `o1js` and signer versions, wallet/CLI versions, endpoints, and the origin of verification keys and proof caches. Load `../mina-protocol-agent/references/playbooks/NETWORK_ERA_AND_O1JS_COMPATIBILITY.md` for Berkeley/Mesa and o1js 3 migration rules. If the era is unknown, label the guidance unverified rather than guessing from package or endpoint names.2122## Current high-risk review additions2324Add these checks to every applicable audit:2526- network era, signer era, transaction JSON, verification key, proof, and cache are mutually compatible;27- state/event/action/AccountUpdate limits are derived from the target era and boundary-tested;28- variable-length commitments use unambiguous length/domain binding;29- `TokenContract.deploy()` permission behavior is verified from the pinned version and on-chain state;30- wallet submission is inspected after proving and before signing;31- submitted, included, archive-indexed, safe, and final are not conflated;32- delegated authority binds mission, agent, app/network, tools/data, budget, expiry, replay control, and receipts.3334Load `../mina-protocol-agent/references/playbooks/TRANSACTION_LIFECYCLE_AND_WALLET_PREFLIGHT.md` and `../mina-protocol-agent/references/playbooks/DELEGATED_AUTHORIZATION_AND_PRIVACY.md` when those surfaces exist. Load `../mina-protocol-agent/references/playbooks/DEPLOYMENT_PROVENANCE_AND_REDEPLOY.md` whenever verification keys, permissions, state layout, deployments, upgrades, key rotation, or runtime configuration are in scope.3536## Safety boundary3738- Do not provide destructive exploitation against third-party systems.39- Do not exfiltrate secrets.40- If secrets appear in files, report minimal evidence and recommend immediate rotation.41- Do not ask the user to paste private keys, seed phrases or production secrets.4243## Review principle4445Mina/o1js security bugs often happen when a developer believes a normal TypeScript check is part of the proof, or when an AccountUpdate/permission path allows something the proof logic did not intend.4647Always separate:4849```text50Ordinary TS runtime check51Provable assertion52State precondition53Signature authorization54Permission authorization55Transaction/AccountUpdate structure56Frontend/backend trust assumption57```5859## Audit workflow6061### 1. Scope capture6263Collect or infer:6465- repository and commit hash;66- o1js version and zkApp CLI version;67- deployed addresses if any;68- target network;69- in-scope files;70- roles: deployer, admin, user, prover, frontend, backend, relayer, oracle, issuer, auditor;71- assets at risk: MINA, custom tokens, credentials, votes, reputation, private data, verification keys;72- high-risk features: tokens, reducers/actions, custom AccountUpdates, recursion, Merkle state, credentials, external data.7374### 2. Architecture map7576Produce this before findings:7778```text79Contracts:80ZkPrograms:81State fields:82Methods and call graph:83Events/actions:84AccountUpdate tree per user flow:85Permissions and upgrade policy:86Frontend/prover/backend flow:87External dependencies:88```8990### 3. Invariant list9192Write project-specific invariants. Examples:9394- only authorized users can update state;95- state transitions bind to the current on-chain state;96- every private witness is constrained to public input or on-chain commitment;97- nullifier can be used only once;98- token supply equals documented mint minus burn plus/minus pending operations;99- all token movements are approved by the intended token owner logic;100- every accepted action can be reduced without permanently bricking the contract;101- admin cannot silently replace verification key unless explicitly documented;102- private data does not appear in public inputs, events, actions, logs or analytics;103- frontend/backend cannot forge a proof or swap public inputs without detection.104105### 4. Code review checklist106107#### Provable constraints108109- Security checks use `assertEquals`, `assertTrue`, `assertFalse`, range assertions or equivalent provable constraints.110- No witness is accepted without being tied to a public root, hash, signature, commitment or state value.111- Conditional logic uses `Provable.if()` correctly and avoids side effects inside branches.112- Fixed-size provable arrays are used where required.113- `Field` modular arithmetic is not used where bounded integer behavior is required.114- Hashes include domain separation.115- Signatures bind all required fields: app id, chain/network id if needed, contract address, action id, nonce/nullifier, amount, recipient, expiry.116117#### State and preconditions118119- Security-critical state reads use `getAndRequireEquals()` or `requireEquals()`.120- Account and network preconditions are explicit for balances, nonce, timestamp, slot, delegate or token state where relevant.121- Stale state and concurrent user flows are handled.122123#### AccountUpdates124125- Every AccountUpdate has the intended account, tokenId, authorization and balance change.126- Child AccountUpdates cannot inherit unintended token powers.127- `mayUseToken` and token ownership are understood and tested.128- `fundNewAccount`, `AccountUpdate.create`, `createSigned`, `approve`, custom send/mint/burn flows are reviewed.129- Transaction shape is stable enough for security assumptions.130131#### Permissions and upgrades132133- Permission matrix is documented.134- `setVerificationKey` and `setPermissions` are not left too loose.135- Least authority is applied.136- Upgrade path is either locked, proof-governed, multisig/timelock-governed or clearly documented as admin-trusted.137138#### Actions/reducers139140- Actions are public and not used for secret data.141- Reducer can process malformed or adversarial actions safely.142- Action type has canonical representation if needed.143- Queue growth, batching and griefing are considered.144- Reduction state cannot be permanently stuck by one bad action.145146#### Privacy147148- Public inputs, events, actions and state do not reveal private values accidentally.149- Backend and frontend do not log private witnesses.150- Nullifiers are domain-separated.151- Timing/IP/wallet metadata risks are documented when privacy claims are made.152153#### Dependencies and devops154155- o1js version is pinned.156- Deprecated APIs are flagged.157- Deployment scripts do not expose keys.158- CI does not print secrets or proofs containing sensitive auxiliary data.159- Frontend integrity and supply chain risks are considered.160161## Finding format162163```text164### [Severity] Title165166Affected files:167Confidence: High / Medium / Low168Category:169Description:170Impact:171Why this happens in Mina/o1js:172Proof-of-concept or exploit sketch:173Recommended fix:174Regression test:175References:176```177178## Severity guide179180- Critical: direct theft, arbitrary mint/burn, arbitrary state update, verification key replacement, permanent fund lock for high-value assets.181- High: unauthorized privileged action, replay of important operation, broken nullifier, severe privacy leak, reducer bricking.182- Medium: missing precondition with realistic race risk, incomplete supply invariant, centralization risk not documented, unsafe upgrade process.183- Low: weak docs, test gaps, non-critical leakage, maintainability issues.184- Informational: hardening suggestion or architectural note.185186## Required output187188For every review, return:1891901. Scope and assumptions.1912. Architecture map.1923. Role model.1934. Permission matrix.1945. AccountUpdate map.1956. Invariants.1967. Findings.1978. Test gaps.1989. Deployment risks.19910. Recommended next steps.200201## Red flags202203- `get()` without `requireEquals()` on state used in security logic.204- `Provable.witness()` without assertions tying it to public data.205- `Field` used as token amount without range/UInt wrapper.206- JS `if` depending on provable values.207- Admin can set verification key by signature without disclosure.208- Token manager approves arbitrary child updates.209- Reducer assumes all actions are honest.210- Events/actions contain PII or secrets.211- Tests only cover happy path.212- README claims privacy but frontend sends raw credential to backend.