CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-3WHF-VGF2-9W6G

GHSA-3WHF-VGF2-9W6G: Denial of Service via Unbounded Recursion and State Panic in zaino-state

Amit Schendel
Amit Schendel
Senior Security Researcher

Jul 31, 2026·6 min read·18 visits

Executive Summary (TL;DR)

zaino-state is vulnerable to unconstrained recursive block reorganization and an unhandled panic during state cache pruning, causing denial of service.

The zaino-state crate contains two critical flaws in its block reorganization and state synchronization logic. An unbounded recursive async function handling block reorganization fails to validate cyclic relationships, enabling network peers to cause infinite loops that exhaust CPU and memory resources. Furthermore, a logical pruning error during non-finalized block cache trimming can purge all cached blocks, triggering an immediate panic and crash of the daemon.

Vulnerability Overview

The zaino-state crate is a core state-tracking component in the Zaino indexer, which indexes and monitors state transitions for the Zcash blockchain. The indexer relies on maintaining a non-finalized state representing potential chain reorganizations (reorgs) prior to transaction finality.

To manage state updates, the component processes incoming blocks and traces changes backward along parent hash pointers to align with the active main chain. This model introduces an attack surface where processed chain metadata influences recursive state traversal. Specifically, malicious or incorrectly formatted inputs can exploit logic paths within the state tracking mechanism.

This advisory tracks two operational vulnerabilities: an unconstrained recursive async loop in handle_reorg and an unhandled panic state within the snapshot cache trimming process. Both vulnerabilities allow an unauthenticated actor to disrupt the availability of the indexing node, leading to resource exhaustion or immediate process crashes.

Root Cause Analysis

The primary vulnerability arises from the implementation of NonFinalizedState::handle_reorg. When the indexer detects a block reorganization, it must verify parent relationships across blocks that are not yet finalized. It achieves this by recursively traversing backward along parent hashes using the prev_hash_bytes_serialized_order method to find a common ancestor.

Because Rust async functions cannot have an unconstrained size at compile time, recursive async functions require heap allocation via pin boxing (Box::pin). However, the implementation of handle_reorg lacked cycle detection and an explicit recursion depth limit. If a node processes a block that references itself as its parent, or a group of blocks that form a cyclic reference graph, the loop executes indefinitely.

The second vulnerability resides in NonfinalizedBlockCacheSnapshot::remove_finalized_blocks. This function trims finalized blocks from the active cache using a simple retain logic (block.height() >= finalized_height). Under extreme network forks or rapid finality shifting, if the finalized_height exceeds the height of all blocks in the cache, the pruning logic retains zero blocks. The downstream code then executes .expect("empty snapshot impossible") on an empty map, triggering an immediate process panic.

Code Analysis

The original vulnerable implementation of the recursive async function structure lacks bounds checks or loop state. The recursive call pattern within handle_reorg was defined as follows:

// Line 459 and 483 in non_finalised_state.rs (Original)
Some(prev_block) => {
    if !working_snapshot
        .heights_to_hashes
        .values()
        .any(|hash| hash == prev_block.hash())
    {
        // Unbounded recursive call allocating a new heap future on every iteration
        Box::pin(self.handle_reorg(working_snapshot, &prev_block)).await?
    } else {
        prev_block
    }
}

The corresponding patch introduces a recursion_count: u8 parameter initialized to 0 at the entry point of the reorganization handler. The function is modified to validate the parameter on each recursive step:

// Patched version showing recursive depth validation
async fn handle_reorg(
    &self,
    working_snapshot: &mut NonfinalizedBlockCacheSnapshot,
    block: &impl Block,
    recursion_count: u8, // Introduced recursion counter
) -> Result<IndexedBlock, SyncError> {
    // Limit recursion to 110 steps to account for complete reorg margins
    if recursion_count > 110 {
        return Err(SyncError::ReorgFailure(
            "reorg handling recursed beyond reason".to_string(),
        ));
    }
    // ...
    // Recursive calls increment the counter
    Box::pin(self.handle_reorg(working_snapshot, &prev_block, recursion_count + 1)).await?
}

For the snapshot pruning panic, the previous logic unconditionally pruned blocks based on height without ensuring the structural integrity of the cache. The patched logic obtains the highest block hash first, ensuring that at least one block is preserved:

// Patched implementation ensuring the top block is retained
fn remove_finalized_blocks(&mut self, finalized_height: Height) {
    let top_block_hash = match self
        .heights_to_hashes
        .iter()
        .max_by_key(|(height, _hash)| *height)
    {
        Some((_height, hash)) => *hash,
        None => return,
    };
    
    // Retain blocks that meet the height requirement OR match the top block hash
    self.blocks.retain(|_hash, block| {
        block.height() >= finalized_height || block.hash() == &top_block_hash
    });
}

Exploitation Mechanics

To exploit the unbounded recursion vulnerability, an attacker must have the capability to feed custom block headers into the indexing pipeline. This occurs if the indexing daemon connects to a malicious validator node, or if the network sync interface accepts block data from untrusted peers.

An attacker constructs a block header where the parent block hash field matches the block's own cryptographic hash:

$$\text{header.previous_block_hash} = \text{block.hash()}$$

When this crafted header is processed, the daemon attempts to trace the history. It extracts the parent hash, retrieves the same block, and recursively calls handle_reorg. Because the recursion relies on Box::pin, every single call allocates memory on the heap while keeping the CPU thread fully saturated.

Alternatively, an attacker can create a multi-block loop (such as A to B to A) to achieve the same infinite recursive state. The thread will spin continuously at 100% CPU usage, rapidly leaking heap space until the platform kernel terminates the process due to out-of-memory constraints.

Impact Assessment

The impact of these two vulnerabilities is a complete Denial of Service (DoS) of the zaino indexer node. Because block synchronization runs within critical application execution contexts, blocking the state reorganization thread stalls all downstream operations.

While the CVSS v4 score is calculated as 5.1 (Medium), the real-world operational impact on indexer infrastructures is significant. A node impacted by the infinite recursion bug remains unresponsive and consumes system-wide computational resources, potentially affecting adjacent applications co-located on the same server instance.

The snapshot pruning panic is deterministic and results in a clean termination of the binary via Rust's panic infrastructure. While a panic does not lead to a resource leak, it terminates the service immediately. If automatic process recovery is not configured, the service remains offline indefinitely.

Remediation & Mitigation Guidance

The primary remediation strategy is upgrading the zaino-state dependency to version 0.4.1 or higher. This version contains the mitigations merged in Pull Request #1172, enforcing a maximum recursion depth of 110 frames and ensuring snapshot stability during pruning.

While the recursion limit successfully prevents the infinite loop, it is a defensive bound rather than a formal cycle detection mechanism. The code continues to process up to 110 recursive heap allocations per malicious block. For comprehensive resilience, operators should restrict validator connections to trusted network peers.

For systems where immediate code updates are not feasible, process supervision is highly recommended. Utilizing monitoring tools like systemd with automatic restart properties ensures that nodes crashing due to the snapshot panic can recover automatically. To handle CPU spikes from recursive loops, resource limits (such as systemd CPUQuota or container-based limits) should be applied to prevent the indexer from degrading overall host performance.

Official Patches

ZingoLabsFix PR for reorganization limits and snapshot panics

Fix Analysis (3)

Technical Appendix

CVSS Score
5.1/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N

Affected Systems

zaino-state indexer nodes

Affected Versions Detail

Product
Affected Versions
Fixed Version
zaino-state
zingolabs
>= 0.0.0, < 0.4.10.4.1
AttributeDetail
CWE IDCWE-770
Attack VectorNetwork
CVSS v4 Score5.1
ImpactDenial of Service (CPU & Memory Exhaustion, Daemon Crash)
Exploit StatusPoC Mechanics Documented
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

The software allocates search or recursion resources without restricting the quantity, allowing consumption of CPU and memory leading to a denial of service.

Known Exploits & Detection

GitHub AdvisoryAdvisory documenting the cyclic block construction vector and memory consumption mechanisms.

Vulnerability Timeline

Original fix for the reorg recursion depth limit committed
2026-06-05
Finalized block trim panic fix committed
2026-06-09
Vulnerability publicly disclosed and published in GHSA database
2026-07-31

References & Sources

  • [1]GitHub Advisory Page for GHSA-3WHF-VGF2-9W6G
  • [2]Advisory Source
  • [3]Fix Pull Request #1172

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•11 minutes ago•CVE-2026-107718
6.1

CVE-2026-107718: Open Redirect Vulnerability in @adonisjs/http-server

CVE-2026-107718 is a medium-severity Open Redirect vulnerability in the core HTTP server package of the AdonisJS Node.js framework. Prior to versions 8.2.3 and 9.3.0, the framework built route paths by directly interpolating dynamic parameters and wildcard segments without URI encoding. If an application routes attacker-controlled input directly to a dynamic first path segment and uses the generated route URL as a redirect destination, a leading slash can produce a scheme-relative external URL. Modern web browsers process scheme-relative URLs by redirecting the client to the specified external domain, exposing users to credential harvesting, social engineering, and session hijacking. This vulnerability affects all applications running unpatched configurations where input validation is not explicitly implemented before generating paths.

Alon Barad
Alon Barad
1 views•6 min read
•about 1 hour ago•CVE-2026-107725
8.7

CVE-2026-107725: Remote Code Execution via Authorization Bypass in Hazelcast Predicates API

CVE-2026-107725 is a critical security bypass in Hazelcast where missing authorization checks in the MapPermission class permit unprivileged clients to issue queries containing aggregators or projections. This architectural oversight allows attackers to run arbitrary code on the cluster servers under the privileges of the active Hazelcast process.

Amit Schendel
Amit Schendel
3 views•7 min read
•about 2 hours ago•CVE-2026-107396
5.4

CVE-2026-107396: Stored Cross-Site Scripting (XSS) in Indico

A stored Cross-Site Scripting (XSS) vulnerability was identified in Indico, an open-source event management system developed at CERN, prior to version 3.3.13. The vulnerability stems from weak URL validation in custom link fields and lack of HTML sanitization during Marshmallow serialization of event notes. This allows authenticated attackers with event modification privileges to inject malicious payloads that execute in the browser of users viewing the event pages or collaborating on notes.

Alon Barad
Alon Barad
3 views•6 min read
•about 3 hours ago•CVE-2026-107397
4.4

CVE-2026-107397: Stored Cross-Site Scripting via Collaborative Editor Conflict Resolution and Custom Link Fields in Indico

A technical analysis of CVE-2026-107397, a stored Cross-Site Scripting (XSS) vulnerability in Indico's collaborative notes editor and custom link generation fields. Prior to version 3.3.13, Marshmallow serialization schemas omitted HTML sanitization during conflict resolution, and form validators failed to enforce strict URI schemes, enabling authenticated low-privilege attackers to execute arbitrary JavaScript.

Alon Barad
Alon Barad
0 views•7 min read
•about 4 hours ago•CVE-2026-107395
4.3

CVE-2026-107395: Missing Authorization in Indico Legacy Session Export API

An authorization bypass vulnerability exists in the legacy session export API of Indico, an open-source event management system developed at CERN. Due to a missing object-level access check, authenticated users can bypass configuration-level restrictions to extract private session metadata (including session titles, descriptions, and list of conveners) from events that they are otherwise authorized to view.

Alon Barad
Alon Barad
8 views•5 min read
•about 5 hours ago•CVE-2026-107394
6.8

CVE-2026-107394: Server-Side Request Forgery Bypass via Parser Differential in Indico

An incomplete Server-Side Request Forgery (SSRF) validation check in Indico prior to version 3.3.13 allows authenticated event organizers to bypass outbound network restrictions. By utilizing backslash characters within crafted URLs, attackers can exploit a parser differential between the application's validator and the downstream HTTP client library to access internal network resources.

Alon Barad
Alon Barad
7 views•6 min read