It happens when a function or method can call itself, directly or indirectly, without a reliable stopping condition or with a condition that can be bypassed. Attackers can trigger stack exhaustion and denial of service. Review base cases, input limits and recursion depth, and prefer iterative logic where unbounded depth is possible.
Why uncontrolled recursion happens
uncontrolled recursion is usually a control-flow problem, not a logic mystery. A function keeps re-entering itself because the stopping condition is missing, too weak, or too easy to bypass. In practice, the recursive path keeps consuming stack frames until the process faults, often turning a bad input pattern into a crash.
The most important distinction is between legitimate recursion and recursion that can grow without a dependable limit. A well-formed recursive routine makes measurable progress toward a base case on every call. Uncontrolled recursion fails that test, so even ordinary-looking input can trigger repeated self-invocation, especially when validation, branch selection, or termination checks are inconsistent.
It can also happen indirectly. A function may call a second function, which eventually routes back to the first one, creating a cycle that is harder to spot in code review than direct self-calls. That is why recursion bugs often survive initial testing, then emerge under edge-case inputs, unusual object graphs, callback chains, or error-handling paths.
How attackers and bad inputs turn recursion into denial of service
When recursion is uncontrolled, the main security consequence is resource exhaustion. Each call uses stack space and often additional CPU, so repeated descent can exhaust process limits before the application can recover. Attackers do not need code execution to exploit this pattern, they only need a request shape, payload, or event sequence that repeatedly drives the same logic path.
In code bases with parsing, tree walking, graph traversal, template expansion, or nested validation, recursion can be a practical denial-of-service mechanism. A maliciously deep structure, a cyclic reference, or an input that defeats the intended base case can keep the call stack growing until the service stops responding. That is especially dangerous in synchronous request handlers, where one bad request can monopolise the worker thread or crash the process.
In this area, the safest reference point is CWE Top 25 Guide, which helps readers connect recursion bugs to broader weakness patterns such as stack overflow, unchecked input, and insufficient resource limits. The practical value is not the label alone, but recognising that a recursion failure is often a broader weakness in bounds enforcement.
What to check in code and design before recursion reaches production
Review the base case first, then the progress condition, then the maximum depth. If any of those three can fail under valid or attacker-controlled input, the routine is unsafe as written. Also check whether the recursive step can be re-entered through indirect calls, callbacks, or exception paths, because those routes are easy to miss when the code looks linear on paper.
Prefer iterative logic when the maximum nesting depth is unknown, attacker-influenced, or large enough to approach stack limits. If recursion is still the clearest design, enforce depth caps, reject pathological inputs early, and make the terminating condition independent of mutable state that the caller can influence. In deeply nested parsing or traversal logic, explicit stack management is usually easier to bound than the native call stack.
For implementation discipline, it helps to treat recursion limits as part of secure input handling rather than as a performance tweak. Tools such as NIST Cybersecurity Framework 2.0 support that mindset by pushing teams to identify exposure, protect critical functions, and detect abnormal failure conditions before they become incidents.
Risk and Threat Considerations
Uncontrolled recursion is risky because the failure mode is often abrupt and systemic: one malformed or maliciously crafted input can drive a service into stack exhaustion, crash a process, or stall a worker pool. The threat is not only an application error, it is an availability weakness that can be triggered repeatedly and cheaply.
Failure mechanism: The recursion path lacks a reliable exit, or the exit can be bypassed by inputs that prevent progress toward the base case. The call chain then grows until stack or process limits are exhausted, and indirect recursion can hide the loop until runtime.
Impact: Affected services may return errors, terminate, or become unresponsive, creating denial of service and potentially cascading failure if the recursion sits in a shared parser, API handler, or background job.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK addresses the attack and risk surface, while CIS Controls v8, NIST CSF 2.0 and OWASP ASVS set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| CIS Controls v8 | CIS-4 — Secure Configuration of Enterprise Assets and Software | Limits unsafe recursion behavior through hardened runtime and app configuration. |
| Recommendation — Set configuration guardrails that bound runtime recursion and reject pathological inputs. | ||
| NIST CSF 2.0 | PR.DS-10 — Data-in-transit is protected | Recursive crashes often emerge from malformed external input reaching parsing logic. |
| DE.CM-01 — Networks and network services are monitored to detect potential cybersecurity events | Stack exhaustion and repeated crashes are observable operational indicators of exploitation or defects. | |
| Recommendation — Validate and constrain externally supplied input before it reaches recursive code paths. Monitor for crash loops and abnormal process termination tied to recursive handlers. | ||
| OWASP ASVS | V2 — Validation and Business Logic | Recursive failures are frequently caused by insufficient validation and bad termination logic. |
| Recommendation — Enforce input validation and business logic checks that prevent unbounded recursive descent. | ||
| MITRE ATT&CK | T1499 — Endpoint Denial of Service | Attackers can weaponize uncontrolled recursion to exhaust stack and deny service. |
| Recommendation — Map crash-triggering recursion to DoS patterns and test for exhaustion conditions. | ||
Practitioner Guidance
What to verify: Confirm that every recursive routine has a base case that is reachable under adversarial input, not only under ideal test data. For externally influenced inputs, validate maximum depth, nesting, and object size before the recursive path begins.
Decision rule: If the depth can grow without a hard business limit, choose an iterative approach or add explicit depth enforcement before release. If recursion remains necessary, instrument failure conditions so stack growth or repeated re-entry is detectable in testing and operations.
Practitioner takeaway: The real control is not “using recursion safely” in the abstract, it is proving that the code cannot keep making calls faster than it can guarantee an exit.
Related resources from NHI Mgmt Group
Deepen Your Knowledge
Free weekly newsletter
Subscribe to the NHI & AI Identity Journal
The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.
Bonus 33% off our NHI Course when you subscribe.
Reviewed and updated by the NHIMG editorial team on October 19, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org