# Unbounded graph traversal recursion

Traversal or error paths that recurse without visited set, depth limit, or cycle check

_Area: Memory corruption and native code. Seen in 4 disclosed reports; 3 confirmed bounties, median $10,000, range $500-$10,000; latest 2023-02-24. Updated 2026-10-23._

## How it works
A walk over a chain or graph assumes it terminates: that each step moves toward an end, or that recursion is bounded by a language-level stack guard. When the structure contains a cycle, or a comparison never matches, the walk revisits nodes forever. In native or C-level recursion the guard may not even apply, because the interpreter's own stack-overflow protection counts Ruby frames, not C frames [E1](https://bugbountylibrary.com/r/h1%3A189633.md). The invariant that must hold — every traversal reaches a terminal state in bounded steps — is silently assumed, not enforced.

## Where it shows up
- Issuer/trust chain walks in `while` loops with no visited set [E2](https://bugbountylibrary.com/r/blog%3Asector7-computest-nl-post-2022-09-unified-automation-opcua-cpp.md)
- Recursive flood-fill or pixel-neighbor routines where a border/color comparison may never be true [E3](https://bugbountylibrary.com/r/h1%3A190863.md)
- Implicit-conversion hooks (`to_i`, `to_s`, `coerce`) that re-enter the VM at C level [E1](https://bugbountylibrary.com/r/h1%3A189633.md)
- Error constructors that call `new` on a class the user can reassign [E4](https://bugbountylibrary.com/r/h1%3A186723.md)
- Single-threaded network handlers doing pre-auth work [E2](https://bugbountylibrary.com/r/blog%3Asector7-computest-nl-post-2022-09-unified-automation-opcua-cpp.md)

## How to review
For each loop or recursive call, ask: what guarantees progress? Identify the termination condition and check it against adversarial input — cyclic chains, mutually-signed certs, negative/out-of-range values, reassigned core classes. Confirm a visited set or explicit depth counter exists, and that the counter tracks the actual recursion level (C frames, not just script frames) [E1](https://bugbountylibrary.com/r/h1%3A189633.md). For error paths, verify the constructor cannot re-trigger the same error [E4](https://bugbountylibrary.com/r/h1%3A186723.md). The property: bounded steps to termination for all inputs, including cyclic and malformed ones.

## Variants seen
- C-level recursion bypassing interpreter stack guard via `to_i` override [E1](https://bugbountylibrary.com/r/h1%3A189633.md)
- Cyclic certificate issuer chain in a `while` loop, pre-auth DoS [E2](https://bugbountylibrary.com/r/blog%3Asector7-computest-nl-post-2022-09-unified-automation-opcua-cpp.md)
- Recursive flood-fill with invalid color on truecolor images [E3](https://bugbountylibrary.com/r/h1%3A190863.md)
- Reassigned exception class causing infinite recursion in error path, corrupting GC [E4](https://bugbountylibrary.com/r/h1%3A186723.md)

## Impact and severity
Crashes, stack exhaustion, and availability loss; E4 escalated to memory corruption via GC stack overflow. Severity rises when reachable pre-auth [E2](https://bugbountylibrary.com/r/blog%3Asector7-computest-nl-post-2022-09-unified-automation-opcua-cpp.md) or inside a sandbox where a crash is a containment failure [E1](https://bugbountylibrary.com/r/h1%3A189633.md)[E4](https://bugbountylibrary.com/r/h1%3A186723.md). Single-threaded handlers and shared interpreters widen blast radius.

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A189633.md
- E2: https://bugbountylibrary.com/r/blog%3Asector7-computest-nl-post-2022-09-unified-automation-opcua-cpp.md
- E3: https://bugbountylibrary.com/r/h1%3A190863.md
- E4: https://bugbountylibrary.com/r/h1%3A186723.md
