# Recursive Agent Loop and Token Budget Exhaustion

- **Severity:** Medium
- **Signature ID:** `6b1f2c9d-7a54-4de8-9c31-2f80a4d5e713`
- **MITRE ATLAS:** AML.T0034 (Cost Harvesting)
- **OWASP:** ASI10 (Resource Exhaustion and Denial of Wallet)

## Summary

This detects an AI agent that repeatedly calls the same tool with the exact same arguments, very fast, without making any real progress. It's the signature of a runaway agent loop that wastes compute, API calls, or money without the attacker (or the agent's own logic) achieving anything new.

## How the attack works

An AI agent session invokes the same tool over and over with byte-identical arguments, at a rapid, machine-like pace rather than human speed. The rule tracks this per agent session, so it never mixes up calls from different sessions. It also checks whether the agent produced any real side effects, like file writes or deletions, during this activity. If a session hits many identical, tightly-spaced calls with no such state change, it flags the loop as non-productive and likely stuck.

## Why it matters

A looping agent can exhaust API quotas, run up cloud or token costs, or tie up shared infrastructure while accomplishing nothing, effectively a denial-of-wallet condition caused by the agent itself rather than a human attacker.

## What you can do

- Set hard caps on tool-call counts and elapsed time per agent session so a stuck loop terminates automatically.
- Add idempotency checks in agent logic so repeated identical calls are detected and skipped instead of re-executed.
- Monitor for agents whose tool calls produce no file, database, or state changes over many consecutive invocations.
- Distinguish legitimate polling patterns (status checks, backoff retries) from true loops by requiring wider, variable intervals between repeated calls.

## Known benign look-alikes

- Long-poll / status-poll tools (get_job_status, wait_for_build) called with identical arguments while an external job runs. Mitigated by the tight-cadence requirement - the mean inter-call gap must be <= 3s; human- or scheduler-paced polling at 5s+ intervals never reaches the threshold.
- Retry-with-backoff against a flaky tool or MCP server. Backoff widens the mean gap on every attempt, so a backing-off retry loop falls out of the tight-cadence gate long before 12 attempts.
- Test harnesses and evaluation suites replaying the same fixture call repeatedly. These are report-only findings and are recognisable by the lineage shown in the kill chain (test runner as session root, not an agent-driven shell).
- Genuinely productive tight loops - a code-mod agent editing files in a loop calls the same tool rapidly but with DIFFERENT arguments (distinct fingerprints), and produces WRITE/CREATE file events. Identical-argument fingerprinting excludes the former; the state-change audit doubles the threshold for the latter.
- Stateful cursor tools where pagination state lives server-side and the client sends identical arguments each page. Rare, and surfaces as report only.

## References

- https://atlas.mitre.org/techniques/AML.T0034
- https://attack.mitre.org/techniques/T1499/
- https://genai.owasp.org/

---
Source: https://www.netzilo.com/threats/recursive-agent-loop-budget-exhaustion
