This is a separate contest from the build contest. Check that out for additional fun!
The Ootle launch is on the horizon. To help refine things ahead of mainnet, and for additional fun and rewards, we’re holding a security bug hunt!
Overview
The Ootle bug hunt is a time-boxed contest in which researchers find and report security vulnerabilities in Tari Ootle for points and bounties. This doc sets the scope, the severity system, the submission process and the disclosure rules. The council sets the contest’s content, point values and bounty amounts.
The standing Tari Vulnerability Disclosure Policy still applies, including its safe harbor, its out-of-scope list and its commonplace reports. Where the two differ, this doc wins for the duration of the contest.
Scope
The target is the tari-project/tari-ootle repository at commit hash 392d805579db35fcc8e8bc1aba84adc1fffe0c22, starting on October 1st and ending at 00:00 UTC November 1st. Only bugs present at that commit count. Bugs introduced later, or already fixed by then, do not.
Trust model
A finding counts only if an attacker within these limits can trigger it:
- Any user submitting arbitrary transactions.
- Any template author deploying arbitrary WASM.
- Any peer on the p2p network.
- A minority of validators: fewer than one third of any committee, acting together.
- For wallet findings, a malicious indexer or a malicious website talking to the wallet.
Attacks that need one third or more of a committee to be Byzantine are out of scope. So are attacks that need control of the Minotari L1 chain.
In scope
Each crate is in one tier. The council can weight points by tier.
| Tier | Area | Crates and applications |
|---|---|---|
| 1 | Consensus and state | consensus, consensus_types, state_tree, epoch_manager, epoch_oracles |
| 1 | Execution and funds | engine, engine_types, transaction, transaction_validation, template_lib, template_abi, ootle_wasm |
| 1 | Built-in templates | account, liquidity_pool, burn_rate_governance |
| 2 | Validator node | tari_validator_node, validator_node_rpc, rpc_state_sync, rpc_framework |
| 2 | Networking | p2p, networking/* (libp2p messaging, peersync, substream, swarm) |
| 2 | Storage and indexing | state_store_rocksdb, storage, tari_indexer, indexer_lib |
| 3 | Wallet and SDK | tari_walletd, wallet, tari_web_extension, ootle_sdk_core, ootle_sdk_ffi_c, ootle_address |
A crate not listed is in scope only if the finding reaches it through a listed crate. In that case it takes the tier of the listed crate.
Out of scope
tari_watcherandtari_swarm_daemon. Researchers may still use the swarm daemon as a test tool.tari_signaling_server.- Test and tooling crates:
consensus_tests,integration_tests,fuzz,template_test_tooling. - The
faucetandnft_faucetbuilt-in templates, community templates and test templates. - The Minotari L1 base layer. L1 bugs go to the standing bounty program.
- Third-party dependencies, unless the report shows an exploit through Ootle code.
- Known issues: open GitHub issues, published advisories, and anything on the known-issues list published when the contest opens.
- Everything in the standing policy’s Out of Scope and Commonplace Reports lists.
Rules of engagement
Test only on infrastructure you run yourself: a local swarm, a private network, or unit and integration tests against the pinned commit.
The following is not allowed, and breaking these rules disqualifies the participant:
- Attacking the public testnet, mainnet, or any node, indexer or wallet you do not own.
- Flooding or load-testing public infrastructure, including bootstrap peers, explorers and websites.
- Social engineering of Tari Labs staff, core contributors, council members or users.
- Sharing finding details with anyone except through the submission channel, including other participants.
- Submitting scanner, fuzzer or AI-tool output without your own analysis and a working proof of concept.
Severity
Severity depends on impact: what the bug lets an attacker within the trust model do, at what cost. Where the bug sits in the code does not set severity; tier is a separate point multiplier. The triage team determines the severity.
| Severity | Points | Impact | Ootle examples |
|---|---|---|---|
| Critical | 20 | Loss of funds, a break in consensus safety, or remote code execution on a validator | Minting or stealing resources from a vault or account; committing conflicting states or double-spending a substate; escaping the WASM sandbox to the host; forging or replaying an L1 burn claim; one unprivileged transaction permanently halting the network |
| High | 7 | Network liveness loss or remote node compromise that recovers, or theft that needs one victim action | Halting a committee, then recovering after restart; crashing any validator remotely with one message or transaction; corrupting a node’s state so it needs a resync; draining a wallet through the wallet daemon’s API or the web extension |
| Medium | 3 | Disproportionate resource abuse, or a limited break of a security property | Executing work without paying fees through cost-metering errors; a DoS needing far less work from the attacker than from the network; a minority of validators stalling progress beyond protocol bounds; crashing an indexer remotely; a malicious indexer tricking a wallet into signing something other than shown |
| Low | 1 | Minor impact, or needs unlikely preconditions | Leaking non-key private data; crashes that need local access; spec deviations with no direct exploit; defence-in-depth gaps with a credible attack path |
Each report also carries a CVSS v4 vector. This keeps the contest in line with the standing policy and makes advisories and CVEs quicker to publish. CVSS is also the tiebreaker for findings on the border between two levels. If CVSS and the impact table disagree, the impact table wins. CVSS does not capture loss of funds, consensus safety, or how far a failure spreads across the network.
These rules adjust the severity:
- Bugs that share a root cause are scored once, at the highest impact shown.
- A chain of findings is scored by the impact of the whole chain. Each link that is also a standalone bug gets its own entry only if fixing it alone needs a separate change.
- Impact must be shown, not assumed. Without a proof of concept, a Critical or High finding is scored as Medium at most.
- An attack that needs unrealistic resources or timing drops one level.
Submission
Submit each finding as a GitHub private security advisory on tari-ootle, with a title starting [Bug Hunt]. If you can’t use GitHub, email security@tari.com with the same subject prefix. Findings sent through any other channel are not accepted, and neither are findings sent after the contest closes.
Each report covers one root cause and must include:
- The affected crate, file and function, at the pinned commit.
- What goes wrong and why, in a few sentences.
- The attacker’s position in the trust model, and the steps of the attack.
- A proof of concept against the pinned commit, such as a failing test, a swarm script or a crafted transaction. Critical and High findings without one are scored as Medium at most.
- The claimed severity and impact, with a CVSS v4 vector.
- A suggested fix (optional; it does not affect the score).
- The payout address for the bounty.
Triage, duplicates and judging
A triage team of core contributors validates each report and assigns a severity.
| Step | Target time |
|---|---|
| Acknowledge receipt | 3 business days |
| Valid, invalid or duplicate decision | 10 business days |
| Report severity to the researcher | 15 business days |
| Final points compiled and prizes after the contest closes | Before December 1st |
- First report wins. Duplicates are matched by root cause. The earliest valid advisory, by GitHub timestamp (or valid email header timestamp for email submissions), gets full credit.
- Known issues. Before the contest opens, the core team publishes a hash of its private list of known, unfixed issues. Any report matching that list is a duplicate. The list is revealed after the contest, so anyone can check it against the hash.
- Disputes. The researcher can contest the severity once, in the advisory thread, with new evidence. The council will weigh in for final decision.
- Invalid reports. These include out-of-scope findings, reports without enough detail to reproduce, and reports that break the rules of engagement. They score zero. Repeated low-effort or spam submissions may disqualify the participant.
Disclosure
All findings stay private until the fix ships and the advisory is published, or 60 days after the report, whichever comes later. Disclosing a finding early forfeits its points and bounty.
- During the contest: only the researcher and the triage team see a report. The public leaderboard shows only each researcher’s handle, finding count and points.
- After a fix: the core team ships the fix in a release, then publishes the GitHub advisory, crediting the researcher by their chosen handle. Each advisory gets a CVE if it qualifies.
- After the embargo: the researcher may publish their own write-up, with technical details. Send a draft to the triage team first so they can check that the advisory has gone out.
- Contest report: after all Critical and High fixes ship, the council publishes a summary of every finding, its severity and its researcher.
If an unfixed Critical finding is still embargoed when the contest ends, the summary leaves it out until the fix ships.
Eligibility, safe harbor and rewards
Anyone may take part, except people who cannot fairly compete:
- Core contributors who wrote or reviewed the affected code are not eligible for that finding.
- Participants must not be barred by sanctions laws from receiving payment.
The standing policy’s safe harbor covers all research that follows these rules.
- Each valid finding earns points equal to its severity’s base points multiplied by its tier’s multiplier.
- At the close, the top three scorers get the top three placement bonuses. The first place prize is 1,000,000 XTM. The second place prize is 500,000 XTM. The third place prize is 250,000. In the event of a tie, the winnings will be split between those holding those placements.
- Payouts go to the payout address in the report, in XTM.
- All valid and accepted reports, regardless of their placement in the contest are also qualified for their standard bounty payout.