If funded this grant will be used to deprecate zcashd, migrate to ironwood, and build a predictable rapid, and adaptable release process.
I agree with the objectives of this grant and the general direction of stabilizing and professionalizing Zaino’s release and operational processes.
From a security perspective, I reviewed Zaino and found 3 low-severity issues and 1 medium-severity issue. The medium issue has already been disclosed via a security advisory:
https://github.com/zingolabs/zaino/security/advisories/GHSA-3whf-vgf2-9w6g
The remaining low-severity findings are being finalized and will be disclosed shortly.
For context, for anyone unfamiliar with why these issues were reported: they were submitted while the ZCG Security & Vulnerability Disclosure Initiative was still active. Although the program has since been closed, Zaino was within scope at the time of submission. My understanding is that any eligible disclosures would still be handled under the legacy process applicable during that period, potentially as part of a future review batch. I’ll defer to @zcg / @artkor for confirmation on the exact process.
That said, since the bug bounty program has ended, I think it would be beneficial to conduct additional security audits and reviews to help ensure any remaining issues are identified and addressed.
Given Zaino’s role as supporting infrastructure, I think continued investment in structured security work—auditing, hardening, and tightening release discipline—is worthwhile. The direction of the grant lines up with that, and also reduces longer-term security risk.
Zaino is not yet ready for use software. As far as I know, not a single team has switched to Zaino. In that case, I do not consider it at all appropriate to talk about identifying bugs of varying degrees of seriousness, except for the most serious ones, which may affect the operation of the higher-level infrastructure.
Quote from the program terms and conditions:
" * Supporting Infrastructure — Zallet, Zaino, and lightwalletd. Findings are capped at High, since defects in these repositories cannot by themselves directly break a core tenet at scale."
Thanks for the context, @artkor.
A few clarifications on my earlier comment, since I think we may be talking past each other.
I was not arguing that Zaino is widely deployed today, or that my findings alone should determine whether this grant is funded. I agree that adoption is still limited. My point was narrower: given Zaino’s stated role as supporting infrastructure and the direction of this proposal, structured security work still seems worthwhile even before broad production use — partly because issues found earlier are cheaper to fix than after wider adoption.
On severity: the medium finding is already public via GHSA-3whf-vgf2-9w6g, and the remaining low-severity items are being finalized for disclosure. I did not assign those ratings for grant leverage; they came out of the normal responsible-disclosure process while the ZCG initiative was still active. I also understand Supporting Infrastructure findings are capped at High and cannot by themselves break a core tenet at scale — that matches how I understood the program scope at submission time.
Happy to keep the grant discussion focused on deliverables and release readiness. I raised security only because the proposal itself includes audit and remediation milestones, not to substitute my reports for that plan.
In my opinion GHSA-3whf-vgf2-9w6g isn’t valid. In production, zaino/lwd runs behind a validator that must check the chain validity. Not having cycles is part of the blockchain rules (chains have to link back to the genesis).
I agree with @hanh zaino trusts the validator for chain-state. That’s explicit in its design.
@hanh @zancas — respectfully, this doesn’t hold: the objection answers a question the bug doesn’t ask.
I also don’t think this thread is the right place for an in-depth discussion, since the focus here is Zaino release stabilization. That said, I do want to briefly explain why I believe this is a valid medium/high severity bug.
**1. Acyclic chains don’t save `handle_reorg`.** It’s a recursive reorg walk with **no depth limit and no cycle/visited check** (`non_finalised_state.rs:468-513`), and it never verifies that a parent fetched by hash actually has the hash it asked for — `get_block` returns whatever the source sends (`validator_connector.rs:57-114`). So termination depends on the bytes on the wire, not on the consensus rules Zebra enforces internally. A self-referencing prev-pointer, or a long fake side-chain that never rejoins the main chain, recurses without bound.
**2. “Trust the validator” is declared, not enforced — and remote validators are supported.** The validator link is **plaintext HTTP** (`connector.rs:1031`), and the docs explicitly allow Zebra on a different host/network (`docker.md:55`; the validator only has to be a private RFC1918 address, not loopback — `config.rs:138-159`). Basic/cookie auth over plaintext gives **no response integrity**, so a MITM, a buggy validator, or a relayed `zcashd`/`zainod` (`validator_connector.rs:44-51`) can feed Zaino a bad block. Trusting the validator for *which block is best* is not the same as guaranteeing it can never **hang or crash** the indexer — and only the first is in the design doc.
**3. The panic needs no attacker at all.** `update()` trims to the finalized height, then `max_by_key(…).expect(“empty snapshot impossible”)` (`non_finalised_state.rs:566-572`). If the non-finalized state ever falls entirely below the finalized tip, that map empties and Zaino panics — from its **own** bookkeeping. The maintainer already conceded this *“isn’t deterministically unreachable.”* “Trust the validator” doesn’t touch this path.
**Impact:** there’s a single sync task — the loop hangs it, the `expect` crashes it, and either way every wallet client behind that Zaino stops getting new blocks. That’s a DoS, not a cosmetic nit.
To be fair: an honest Zebra over loopback won’t hand Zaino a cyclic block, and there’s no anonymous-internet reach in a single-host setup — which lowers the **severity** (hence Medium, High if the link is remote), not the **validity**. The maintainer has already written the recursion-depth fix and called it top-priority reorg hardening. You don’t bound a loop and swap an `expect` for an error to patch a non-bug.
Corrupt/Bogus validator puts Zaino out of the operational zone. Anything that happens in this situation is fair game. It’s like: If you put diesel in your gas engine, the car is not under warranty.
The maintainer can decide to add a protection, but it doesn’t change that fact.
I agree that this is out-of-scope for this thread, responding here instead.
@zancas at the most recent meeting, ZCG voted to approve this proposal. Congratulations!
To keep the community informed, ZCG requests that you provide monthly updates via the forum in this thread.
Please check your forum inbox for a direct message from FPF with important next steps, including a link to the Milestone Payment Request Form and your unique validation code for submitting payment requests.
Thanks! 'Back to the code.
We’ve released a new version of Zaino[d]!