Terms and Conditions
- I agree to the Grant Agreement terms if funded
- I agree to Provide KYC information if funded above $50,000 USD
- I agree to disclose conflicts of interest
- I understand that this grant program is only eligible for completed work, as it is a retroactive grant program. Applications for planned or partially completed work will not be considered. All completed work will be verified and accepted by its intended users or their representatives, who will confirm that the outputs meet the required quality, functionality, and usability before the work is listed as an option for Coinholder voting.
- I agree that for any new open-source software, I will create a CONTRIBUTING.md file that reflects the high standards of Zcash development, using the
librustzcashstyle guides as a primary reference. - I understand when contributing to existing Zcash code, I am required to adhere to the project specific contribution guidelines, paying close attention to any merge, branch, pull request, and commit guidelines as exemplified in the librustzcash repository.
- I understand all grants are valued in USD but will be disbursed in Shielded ZEC. I acknowledge and accept that disbursement amounts may fluctuate based on the ZEC/USD exchange rate at the time of payment.
Application Owners (@octocat, @octocat1)
@octocat, @octocat1
Organization or Individual Name
@x15-eth
Additional Team Members
None. I am applying as an individual, for my own share of each advisory.
Each advisory's other credited researchers are named below. I claim only my equal share, and
nothing on their behalf. Remediation was done by the Zcash Foundation's Zebra team (structured
credits include @conradoplg, @upbqdn, @oxarbitrage and @mpguerra).
How did you learn about the Lockbox: Coinholder Retroactive Grants Program?
Zcash Community Forum: the Q3 call for proposals and the Q3 results thread.
Requested Grant Amount (USD)
100000
Category
Research & Development
Project Summary
In plain terms:
- Zebra 7.0.0, the release every node needs for NU7, fixed four High-severity bugs that credit me.
- Before the fixes, a single connected peer could make any Zebra node burn its CPU for as long as it kept sending, slow its block verification, or stop its initial sync, and was never banned.
- I am asking for $100,000: my equal share of ZCG's published High rate on the three of them where ZF names what my report contributed.
- I claim nothing for the fourth, GHSA-9hq5, where ZF names no contribution of mine.
- I also claim nothing for an earlier advisory I was already paid for, and no bonus.
Project Description
Claim policy
- Only findings the Zcash Foundation has fixed and published, where ZF credits me as a reporter, first or independent, and names what my report contributed.
- I claim only my equal share of each advisory's ZCG base payout, split among every researcher ZF credits on it. If every credited researcher claimed the same way, the total paid per advisory would never exceed one payout.
- High-severity advisories only, at ZF's published rating.
- Anything already paid is deducted. No bonus.
- If ZCG reopens a bounty program, I will use it before asking coinholders.
The completed work
| Advisory (all High) | Researchers ZF credits | My named contribution (ZF's words) | My share |
|---|---|---|---|
| GHSA-jq45-ghw5-v37x: transparent script failures are never scored, on the mempool, block-sync and block-gossip paths | me (reporter), @ouicate (independent rediscovery and further analysis: ZF says ouicate "showed the block-sync and block-gossip consequences") | "Reported by @x15-eth, who also measured the combined effect with GHSA-j4cw-58mj-7w6v" | $37,500 |
| GHSA-2w9f-9wx8-f5c8: a sync restart during a failed checkpoint commit loses the verifier rewind, stalling checkpoint sync until restart | @SphereDonout (reporter), me (independent) | "showed that the issue affects every NU5 or later checkpoint range and identified the unscored UnexpectedSideChain trigger and the AlreadyVerified path, with crate-level tests" | $37,500 |
| GHSA-j4cw-58mj-7w6v: quadratic signature-hash cost, so one transaction stalls block verification for minutes | @asafmod (reporter), me and @janneh2000 (independent rediscoveries) | "Independently reported by @x15-eth who also measured the v4 path and the effect on block verification and memory" | $25,000 |
| GHSA-4m69-67m6-prqp (CVE-2026-52736): block suppression via same-header body poisoning, fixed in 4.5.0 | @ipwning and me (co-reporters) | "first reporter, with E2E reproduction and control experiment" | $37,500 − $37,500 already paid = $0 |
| Total | $100,000 |
All three claimed advisories are rated CVSS 3.1 7.5, and were fixed in Zebra 7.0.0. GHSA-4m69 was fixed earlier, in 4.5.0.
Not claimed: GHSA-9hq5-pfgc-cx5h (High). ZF lists me as one of four independent re-discoverers, after the original reporter, with no contribution of mine named.
What my independent work added, where I wasn't the first reporter:
- GHSA-2w9f:
- ZF's advisory lists the unscored
UnexpectedSideChaintrigger I found as one of its two confirmed triggers. It's the one that lets the attacker repeat the stall, because it carries a misbehavior score of 0. - ZF's fix also covers the
AlreadyVerifiedpath my report identified: the syncer now requests those honest blocks again.
- ZF's advisory lists the unscored
- GHSA-j4cw:
- ZF's credit names the v4 (ZIP-243) path, which I measured, and its effect on block verification and memory.
- The fix covers that path too: it precomputes "the ZIP-243 prevouts, sequence and outputs digests for v4 transactions" once per transaction.
- ZF's j4cw advisory also lists the GHSA-jq45 fix as part of the remedy, because it means "the sender of such a transaction is now banned".
Why it mattered
One connected peer could delay block verification on any synced Zebra node, or stop a new node's initial sync, and was never penalized. With zcashd retired, Zebra is the main full node the network runs on.
- CPU flood (GHSA-jq45). This hit every synced node in its default configuration. In ZF's words, "any inbound or outbound peer can trigger it after the handshake", and "No configuration change exposes or protects you".
- Zebra's 100-point ban score for invalid transparent scripts could never fire, because of a type-conversion gap. The node rejected every bad transaction but never banned the sender, like a smoke detector with its siren unplugged. That was true of every release from 2.3.0 (May 2025) to 7.0.0-rc.0.
- So a peer could repeat the most expensive check in Zebra's transaction verifier without limit. In the 23,500-input transaction I measured, each attempt cost about 85 CPU-seconds, and a peer could keep five in flight per IP address. Most of that per-transaction cost came from GHSA-j4cw, below. The missing ban in jq45 is what let a peer keep repeating it.
- ZF's GHSA-jq45 advisory gives the effect: "Block verification shares the same thread pool, so blocks were verified late while the attack lasted", and honest transactions waiting behind the same work "were dropped if they waited longer than the 73-second verification timeout."
- Creating the 23,500 small outputs the transaction spends cost about 1.2 ZEC in fees, once. Because the transaction is always rejected, the outputs are never spent, and the sender is never banned. So the same outputs can fund the attack for as long as the attacker likes, against every node it can connect to.
- Quadratic signature-hash cost (GHSA-j4cw). This also hit every node, from any peer or any caller that can reach
sendrawtransaction.- One transaction of at most 2 MB made Zebra do hashing work that grows with the square of its input count, on the same thread pool that block verification uses. The work kept running after the transaction was rejected.
- For the original reporter's largest transaction, ZF's advisory puts the cost at "about 7 minutes of stalled verification on a 4-core node", adding: "A mining node cannot verify new blocks during that time and its templates go stale."
- The rejection carried no misbehavior score, so the sender was not disconnected or banned.
- Initial sync stall (GHSA-2w9f). This one is narrower. It hits nodes doing checkpoint sync, which ZF lists as "a new node, a node re-syncing from scratch, or a node restarting from a cached state below the final checkpoint".
- A single peer could stop such a node until restart, then do it again in the next range.
- My report showed this covers every NU5-or-later checkpoint range, which is about 1.8 million blocks of Mainnet initial sync. It also found the unscored trigger that lets the attacker repeat it.
What these bugs are not. They are availability bugs. As ZF's advisories say, none of them crashes a node, corrupts state, splits consensus or touches funds, and the effects stop when the attack stops. The case for paying them rests on reach and persistence: any peer, any default node, never banned, for as long as the attacker likes.
These are exactly what ZCG's own guide calls High. ZCG's (now closed) disclosure program defined High with examples including "Non-distributed denial of service against an individual node or wallet", and priced a Core Node High at $75,000. The rate used here is ZCG's number for this class of bug, not mine.
Why this is what the program is for
- It is exactly the kind of work coinholders chose to fund. In 2025, coinholders voted to run the Coinholder-Controlled Fund (ZIP 1016) as a retroactive program (ratification poll): it pays only for finished, publicly verifiable work, so coinholders carry no execution risk. Every item here is already fixed, merged, released and published, and credited by name.
- Anyone can check it. ZIP 1016 aims for decentralized, accountable funding decisions. Each claim here is in ZF's public advisories, its changelog or the Zebra 7.0.0 release, so anyone can check it without taking my word for it.
- There is no other paying route for security research. ZF does not pay for reports (Zebra's
SECURITY.md: ZF does "not currently operate a bug bounty program and do not pay for reports"). ZCG closed its program on 26 May 2026, after AI-generated, often unverified reports overwhelmed triage. I filed these reports on 6 and 7 October 2026. - It keeps responsible disclosure worthwhile. Paying for fixed, verified disclosures keeps private reporting more attractive than exploiting a bug or disclosing it publicly. That is why Q3 coinholders funded the Orchard disclosure and several Zebra findings.
- For scale: in Q3, coinholders funded a single Critical Zebra DoS at $150,000. This request is $100,000 for my shares of three Highs.
Basis for the $100,000 request
| ZCG Core Node tier | Base payout | Discretionary bonus (not claimed) |
|---|---|---|
| Critical | $150,000 | $75,000 |
| High | $75,000 | $37,500 |
| Medium | $37,500 | $18,750 |
| Low | $18,750 | $9,375 |
Equal split per advisory, as funded in Q3:
- GHSA-jq45: $75,000 ÷ 2 = $37,500.
- GHSA-2w9f: $75,000 ÷ 2 = $37,500.
- GHSA-j4cw: $75,000 ÷ 3 = $25,000.
- GHSA-4m69: $75,000 ÷ 2 = $37,500, minus the $37,500 already received, which leaves $0.
This is the method sangsoo-osec used in Q3 ("Five Critical Zebra Consensus Divergence Vulnerabilities", funded with 96% approval, per the published tally). He claimed half of GHSA-8m29, where ZF credits him as having "independently found the same issue" and shown an extra variant, alongside the original reporter's own claim.
Technical Approach (how you did it)
I ran this review with Claude (Anthropic's AI model) as the research engine, and directed it. Rather than relying on unverified model output, I used it to generate focused hypotheses, to write and run the tests that confirmed or killed each one, and to draft the reports for the findings that survived. My part:
- I set the targets and the evidence bar;
- I chose which leads to pursue and which to drop;
- I decided what to report, and at what severity;
- I submitted each report, and saw it through ZF's triage.
- Learn from past advisories. The review started from a model of what Zebra's published Critical and High advisories had in common: places where, by the time a failed check is acted on, the error no longer means what the code assumes.
- Generate focused hypotheses. Each lead named one concrete place where that could happen, such as a ban score that can't fire, or a recovery step that can be cancelled.
- Confirm or kill with real code. Every lead had to pass a test through Zebra's real code paths, such as the real transaction verifier,
CheckpointVerifierandStateService, with a negative control. Leads that didn't survive were dropped, not reported. - Measure the impact. For jq45: CPU time per transaction, the queue against the 73-second timeout, and the attacker's setup cost. ZF's advisory uses those figures.
- Report privately and reproducibly. Each report went through Zebra's private advisory process, with the full proof-of-concept diff and its control case. ZF reproduced, fixed and published each one.
GHSA-jq45.
- Every 100-point arm of the misbehavior table was traced back to the code that constructs its error. The
Script(_)arm had no live constructor on the verification path, so script failures reached the table asInternalDowncastError, which scores 0. - A proof-of-concept test against the real transaction verifier, with a negative control, confirmed it.
- The cost a peer could impose was then measured, including the v4 path: a 23,500-input transaction, its CPU time, and the queue behaviour against the 73-second timeout. ZF's advisories use those figures.
GHSA-2w9f.
- Following the checkpoint verifier's rewind path showed that the only step that rewinds it runs inside a future the syncer cancels on restart.
- The report then found an unscored way to force that restart (
UnexpectedSideChain). - Crate-level tests against the real
CheckpointVerifierandStateService, using real NU5 Regtest blocks mined byzebrad, showed the stall in any NU5-or-later range, with honest re-deliveries dropped asAlreadyVerified.
GHSA-j4cw.
- Tests through Zebra's real signature hasher, with signatures that are well formed but never verify, showed that each input's signature hash re-hashes data covering every input. The cost per input grows with the input count, so the cost per transaction grows with its square.
- The tests covered both the v5 (ZIP-244) path and the v4 (ZIP-243) path, and then measured the effect on block verification and memory.
Disclosure. All reports went privately through Zebra's GitHub security advisory process. I worked with the team through triage, and kept details private until fixes shipped and operators had been told to upgrade.
Time Period of Work Completion
October 2026: reports filed on 6 and 7 October 2026, fixed in Zebra 7.0.0, and published on 22 October 2026. GHSA-4m69 (listed, $0 claimed) dates from May 2026.
Total Budget (USD)
0
Budget Breakdown
- Compensation:
- $(USD): 0
- Justification: This is a bounty for completed, accepted security outcomes, valued as equal shares of ZCG's published Core Node schedule. It is not a reimbursement of hours.
- Technology/Software:
- $(USD): 0
- Justification: AI-assistant and compute costs are not claimed.
- Infrastructure/Hosting:
- $(USD): 0
- Justification: None claimed.
- Services/Contractors:
- $(USD): 0
- Justification: None.
- Other:
- $(USD): 0
- Justification: None.
- Total $(USD): 0 in costs. The $100,000 requested is my share of the outcomes, per the basis above.
Previous Funding
No
Previous Funding Details
I have not received funding from the Coinholder Retroactive Grants Program.
Other Funding Sources
Yes
Other Funding Sources Details
- 10 June 2026: $37,500 (86.36 ZEC) under ZCG's Security & Vulnerability Disclosure Initiative, for my half of GHSA-4m69-67m6-prqp / CVE-2026-52736, which I co-reported with @ipwning before the program closed. It appears on FPF's public payout record, and it is deducted in full above.
- A May 2026 tweet from @0x15_eth mentions "a $75,000 bounty". That was the total for that advisory, shared between two researchers. My share was the $37,500 above.
- No other payment has been received, or is pending, for any advisory in this application. Anything that ever arises will be disclosed and deducted dollar-for-dollar before disbursement.
- This is my first of two proposals this round. The second covers a separate, later-published advisory.
Time Period of Work Completion
October 2026: reports filed on 6 and 7 October 2026, fixed in Zebra 7.0.0, and published on 22 October 2026. GHSA-4m69 (listed, $0 claimed) dates from May 2026.
Total Budget (USD)
0
Budget Breakdown
- Compensation:
- $(USD): null
- Justification: null
- Technology/Software:
- $(USD): null
- Justification: null
- Infrastructure/Hosting:
- $(USD): null
- Justification: null
- Services/Contractors:
- $(USD): null
- Justification: null
- Other:
- $(USD): null
- Justification: null
- Total $(USD):
Previous Funding
No
Previous Funding Details
I have not received funding from the Coinholder Retroactive Grants Program.
Other Funding Sources
Yes
Other Funding Sources Details
- 10 June 2026: $37,500 (86.36 ZEC) under ZCG's Security & Vulnerability Disclosure Initiative, for my half of GHSA-4m69-67m6-prqp / CVE-2026-52736, which I co-reported with @ipwning before the program closed. It appears on FPF's public payout record, and it is deducted in full above.
- A May 2026 tweet from @0x15_eth mentions "a $75,000 bounty". That was the total for that advisory, shared between two researchers. My share was the $37,500 above.
- No other payment has been received, or is pending, for any advisory in this application. Anything that ever arises will be disclosed and deducted dollar-for-dollar before disbursement.
- This is my first of two proposals this round. The second covers a separate, later-published advisory.
Success Metrics
Quantitative
- Severity assigned by the remediation team: High, CVSS 3.1 7.5, for each claimed advisory.
- Exposure:
- GHSA-jq45: every zebrad release from 2.3.0 (May 2025) to 7.0.0-rc.0, about 17 months, every default configuration.
- GHSA-2w9f: about 1.8 million blocks of Mainnet initial sync.
- GHSA-j4cw: every zebrad release before 7.0.0.
- Attacker cost: ordinary peer connections, no proof of work, no keys. About 1.2 ZEC once for the CPU flood.
- Measured harm: about 85 CPU-seconds per 2 MB transaction in my measurement, five held in flight per IP, block verification delayed, honest transactions dropped, the attacker never banned. For j4cw, ZF's advisory gives about 7 minutes of stalled verification on a 4-core node for the original reporter's largest transaction.
Advisories that credit me
Everything below is published and credits me:
| Advisory | Severity | Fixed in | My credit |
|---|---|---|---|
| GHSA-jq45 | High | 7.0.0 | Reporter |
| GHSA-2w9f | High | 7.0.0 | Independent, with a named contribution |
| GHSA-j4cw | High | 7.0.0 | Independent, with a named contribution |
| GHSA-9hq5 | High | 7.0.0 | Independent reporter (not claimed) |
| GHSA-4m69 | High | 4.5.0 | Co-reporter (already paid) |
Qualitative
- The fixes close whole classes.
- Script failures now get the sending peer banned.
- The checkpoint verifier's rewind can no longer be cancelled.
- Each input's signature hash now costs the same however many inputs the transaction has.
- Coordinated disclosure, done the way the ecosystem asks. Private reports, test-backed evidence, help with triage, and no public details before the fixes shipped.
On the arguments against this application
- "These are just DoS bugs, and High overstates them."
- They are DoS bugs, and I say so above. But GHSA-jq45 and GHSA-j4cw hit every node in its default configuration, from any peer. GHSA-2w9f hits syncing nodes, which includes every new node.
- The severity isn't mine. ZF rated each advisory High (CVSS 7.5) after reproducing it, and ZCG's schedule defines single-node DoS as High.
- The claim limits itself. I claim only my equal share, with no bonus and the earlier payment deducted. If each credited researcher claims an equal share, the total stays within the $225,000 that ZCG's schedule pays for these three advisories.
- "You're claiming bugs other people found, with AI help."
- I claim only where ZF credits me as a reporter and names what my report added: jq45 (reporter), 2w9f (the unscored trigger) and j4cw (the v4 path). I claim only my equal share. Q3 funded the same split for GHSA-8m29.
- The AI use is disclosed above. What ZCG's program closed over was unverified output. Every one of these was confirmed by a passing test against Zebra's real code before I reported it, then reproduced, fixed and published by ZF, which credits me by name.
Proof of completion
- Repository/Commit:
- GHSA-jq45 fix: commit abd875cb8 - "fix(consensus)!: fix scoring for transparent script failure", via PR #11877 "combined security fixes for 7.0.0"
- GHSA-2w9f, part of the fix: commit 3017b60d6 - "reset checkpoint progress even when the verify future is dropped"
- GHSA-j4cw fix: commit e6644c2ea - "update zcash_primitives to avoid quadratic allocation during verification", on the same security branch as the jq45 fix
- Publication:
- GHSA-jq45-ghw5-v37x - High 7.5; structured credit: x15-eth (reporter)
- GHSA-2w9f-9wx8-f5c8 - High 7.5; the credit section names my contribution
- GHSA-j4cw-58mj-7w6v - High 7.5; reporter line "@asafmod ; @x15-eth and @janneh2000 (independent rediscoveries)", and the credit section names my contribution
- GHSA-4m69-67m6-prqp - High; structured credit: @ipwning and x15-eth (reporters)
- Zebra 7.0.0 CHANGELOG - "Thanks to @x15-eth for reporting the issue" (GHSA-jq45)
- Deployment/Release:
- Zebra 7.0.0 - 22 Oct 2026, the release every Mainnet operator needs before NU7
- Other Evidence:
- Zebra 7.0.0 release announcement - credits @x15-eth on GHSA-jq45 ("for reporting this issue"), GHSA-j4cw ("for independent rediscovery") and GHSA-9hq5
- ZCG disclosure program - its severity definitions and Core Node payout schedule
Conflict of Interest Disclosure
None.
- I have no employment, contracting or governance relationship with the Zcash Foundation, FPF, ZCG, ZODL, Shielded Labs or any keyholder organization.
- I have no role in administering this program.
- My only prior payment from the Zcash ecosystem is the ZCG payment disclosed above.
Community Forum Posting
- I understand it is my responsibility to post a link to this issue on the Zcash Community Forums after this application has been submitted so the community can give input. I understand this is required in order for the community to discuss and vote on this grant application. Note: If you are unable to post on the forum (for example, due to new user restrictions), please leave a comment below, and we will adjust your posting permissions.