Back to Intelligence

OWASP LLM Unbounded Consumption: How AI Agents Trigger Runaway Cloud Costs — Detection and Guardrail Guide

SA
Security Arsenal Team
September 21, 2026
12 min read

Dark Reading recently highlighted a risk that most security teams are still underestimating: unbounded consumption in LLM-powered applications and autonomous AI agents. OWASP currently ranks this sixth in its Top 10 for LLM Applications, and unlike many entries on that list, this one doesn't require a sophisticated adversary to hurt you — your own well-intentioned agent can do it. A recursive agent loop, a prompt injection that forces infinite tool calls, or a denial-of-wallet attack from an external actor can turn a $500/day AI workload into a six-figure cloud bill before your finance team even sees an alert.

This is not theoretical. As enterprises move from single-shot LLM integrations to agentic architectures — where models plan, invoke tools, call APIs, and chain outputs into new prompts autonomously — the blast radius of a runaway process grows from "expensive API call" to "the agent is autonomously provisioning resources, calling paid third-party APIs, and retrying failed loops 10,000 times per hour."

Security teams own this problem now. Budget exhaustion is an availability attack, and availability is a security control. Here's how to detect it, contain it, and architect against it.

Technical Analysis: How Unbounded Consumption Actually Happens

The Attack and Failure Surface

Unbounded consumption in agentic systems manifests through several distinct mechanisms, each with different observables:

1. Agentic recursion and tool-call loops. Autonomous agents that can call tools and feed outputs back into new prompts can enter non-terminating loops. A planner agent that keeps deciding it "needs one more step" or two agents that delegate tasks back and forth will generate thousands of inference calls with no human in the loop. Unlike a human user, an agent doesn't get bored or stop at 2 AM.

2. Prompt-injection-driven resource exhaustion. An attacker who can reach any input the agent consumes — a web page it scrapes, an email it summarizes, a document it indexes — can inject instructions that force expensive behavior: repeated high-token generation, calls to the most expensive model tier, or loops through paid external APIs. This is the classic indirect prompt injection path weaponized against your billing account instead of your data.

3. Denial-of-wallet / economic DoS. Adversaries deliberately flood publicly exposed LLM endpoints with high-token requests to inflate costs and degrade service. If your LLM-backed feature is internet-facing without per-identity throttling, this is trivial to execute.

4. Context window abuse. Attackers or buggy upstream integrations submit maximum-length inputs on every call. Since token consumption scales with input size, a feature designed around 2K-token prompts quietly becomes a 128K-token-per-request cost center.

5. Model downgrade inversion / tier abuse. Agents misconfigured (or manipulated) to route all traffic to premium models when a cheaper tier would suffice, multiplying per-call cost 10–50x.

Why Traditional Controls Miss This

Most organizations deploy LLM workloads with cloud budgets set at the account level — alerts that fire hours after the money is spent, not controls that stop the bleed. WAFs don't inspect semantic request cost. API gateways count requests, not tokens. And critically, the agent's own identity often has broad authorization, so nothing in your IAM stack views "agent calls paid API 40,000 times" as anomalous.

The exploitation status here is active and structural: this is not a single CVE with a patch — it is an architectural weakness in how most organizations deploy agentic AI in 2025–2026, and OWASP's ranking reflects how commonly it's being hit in production.

Detection & Response

The detections below target the observable behaviors of runaway consumption: abnormal outbound call volume to LLM API endpoints, processes spawning excessive API traffic, and per-principal request anomalies in your logs.

Sigma Rules

YAML
---
title: High-Volume Outbound Connections to LLM API Endpoints
id: 3f9a1c74-8b2e-4d91-a6f3-5c7e2b8d9012
status: experimental
description: Detects processes establishing repeated network connections to public LLM API endpoints. Baseline your legitimate agent workloads first; alert on hosts that have no business calling LLM APIs or on abnormal frequency from known agents.
references:
  - https://genai.owasp.org/llmrisk/llm10-unbounded-consumption/
  - https://attack.mitre.org/techniques/T1102/
author: Security Arsenal
date: 2026/02/14
tags:
  - attack.command_and_control
  - attack.t1102
logsource:
  category: network_connection
  product: windows
detection:
  selection:
    DestinationHostname|contains:
      - 'api.openai.com'
      - 'api.anthropic.com'
      - 'generativelanguage.googleapis.com'
      - 'api.mistral.ai'
      - 'api.cohere.com'
      - 'openai.azure.com'
      - 'bedrock-runtime'
      - 'api.x.ai'
  filter_known_agents:
    Image|endswith:
      - '\node.exe'
      - '\python.exe'
      - '\python3.exe'
  condition: selection and not filter_known_agents
falsepositives:
  - Developer workstations testing LLM integrations
  - Legitimate SaaS AI features embedded in business applications
level: medium
---
title: Suspicious Scripting Process Spawning Rapid Sequential Network Activity
id: 8c4e2b16-7a3d-4f52-b9e1-2d6a5c0f8347
status: experimental
description: Detects scripting interpreters and automation runtimes commonly used to host AI agents spawning child processes in rapid succession — a pattern consistent with agentic tool-call loops and recursive task execution.
references:
  - https://genai.owasp.org/llmrisk/llm10-unbounded-consumption/
author: Security Arsenal
date: 2026/02/14
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    ParentImage|endswith:
      - '\python.exe'
      - '\python3.exe'
      - '\node.exe'
      - '\deno.exe'
    Image|endswith:
      - '\curl.exe'
      - '\wget.exe'
      - '\powershell.exe'
      - '\cmd.exe'
      - '\certutil.exe'
  condition: selection
falsepositives:
  - CI/CD pipeline agents
  - Legitimate automation frameworks (Ansible, orchestration workers)
level: medium
---
title: LLM API Key or Agent Configuration Access From Unexpected Process
id: b1d7e493-2c8f-4a65-9d3b-7e4f1a2c6598
status: experimental
description: Detects processes reading files or environment blocks that commonly contain LLM API keys or agent framework configuration — a precursor to key theft enabling attacker-driven consumption abuse.
references:
  - https://genai.owasp.org/llmrisk/llm10-unbounded-consumption/
author: Security Arsenal
date: 2026/02/14
tags:
  - attack.credential_access
  - attack.t1552
logsource:
  category: file_event
  product: windows
detection:
  selection:
    TargetFilename|contains:
      - '\.env'
      - 'openai_api_key'
      - 'anthropic'
      - '\.config\openai'
      - 'agent_config'
      - 'langchain'
      - 'credentials.json'
  filter_legit:
    Image|endswith:
      - '\code.exe'
      - '\python.exe'
      - '\node.exe'
      - '\msbuild.exe'
      - '\devenv.exe'
  condition: selection and not filter_legit
falsepositives:
  - Developers editing environment files
  - Backup and indexing software
level: low

KQL — Microsoft Sentinel / Defender Hunt

This query identifies principals (hosts, service accounts, managed identities) generating abnormal outbound volume to LLM endpoints — the primary telemetry signature of a runaway agent or denial-of-wallet event. Run it against Defender network events and your firewall/proxy ingestion.

KQL — Microsoft Sentinel / Defender
let llm_domains = dynamic(["api.openai.com", "api.anthropic.com", "generativelanguage.googleapis.com", "api.mistral.ai", "api.cohere.com", "api.x.ai", "bedrock-runtime"]);
let lookback = 24h;
let baseline_days = 7d;
// Establish 7-day hourly baseline per device
let baseline = DeviceNetworkEvents
| where TimeGenerated between (ago(baseline_days) .. ago(lookback))
| where RemoteUrl has_any (llm_domains)
| summarize BaselineAvg = avg(todouble(count_)) by DeviceName, bin(TimeGenerated, 1h)
| summarize AvgHourlyCalls = avg(BaselineAvg) by DeviceName;
// Current 24h volume per device
DeviceNetworkEvents
| where TimeGenerated > ago(lookback)
| where RemoteUrl has_any (llm_domains)
| summarize CurrentCalls = count(), DistinctEndpoints = dcount(RemoteUrl), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName
| join kind=leftouter baseline on DeviceName
| extend DeviationRatio = round(todouble(CurrentCalls) / todouble(coalesce(AvgHourlyCalls, 1.0) * 24.0), 2)
| where CurrentCalls > 500 or DeviationRatio > 5
| project DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName, CurrentCalls, AvgHourlyCalls, DeviationRatio, DistinctEndpoints, FirstSeen, LastSeen
| sort by DeviationRatio desc;

Companion query for proxy/firewall ingestion (CEF/Syslog) to catch consumption spikes at the network edge where endpoint agents aren't deployed:

KQL — Microsoft Sentinel / Defender
let llm_domains = dynamic(["api.openai.com", "api.anthropic.com", "generativelanguage.googleapis.com", "api.mistral.ai", "api.cohere.com", "openai.azure.com"]);
CommonSecurityLog
| where TimeGenerated > ago(6h)
| where DestinationHostName has_any (llm_domains)
| summarize Requests = count(), UniqueSources = dcount(SourceIP), BytesOut = sum(tolong(SentBytes)) by SourceIP, DestinationHostName, bin(TimeGenerated, 15m)
| where Requests > 100
| sort by Requests desc;

Velociraptor VQL — Endpoint Hunt for Agent Processes

Use this hunt to identify which processes on a host hold active connections to LLM API infrastructure — critical when scoping a runaway agent for containment.

VQL — Velociraptor
-- Identify processes with active connections to LLM API endpoints
-- Scope runaway agent consumption events for containment
LET llm_ips <= SELECT * FROM netstat()
WHERE RemoteIP =~ '^(104\.18|3\.163|34\.|35\.|52\.)'
  AND Status =~ 'ESTABLISHED'

SELECT Pid,
       Name,
       LocalIP,
       LocalPort,
       RemoteIP,
       RemotePort,
       Status
FROM netstat()
WHERE RemotePort = 443
  AND Status =~ 'ESTABLISHED'
  AND Name =~ '(?i)(python|node|deno|langchain|agent)'

For deeper scoping, pair with a process listing to pull full command lines of suspected agent runtimes:

VQL — Velociraptor
-- Enumerate candidate AI agent processes with full command lines
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(openai|anthropic|langchain|llamaindex|autogen|crewai|agent)'
   OR Name =~ '(?i)(python|node|deno)'
ORDER BY CreateTime DESC

Cost Guardrail and Containment Script

For Azure OpenAI / Azure-hosted workloads, this PowerShell script verifies budget alerts exist, checks for action groups wired to those budgets (so alerts actually reach someone), and inventories AI-related resource deployments. Adapt the subscription scope to your environment.

PowerShell
# AI Consumption Guardrail Audit — Azure
# Verifies budget alerts, action groups, and inventories AI resource deployments

$ErrorActionPreference = 'Stop'
$context = Get-AzContext
if (-not $context) { Connect-AzAccount }
$subId = $context.Subscription.Id
Write-Output "[*] Auditing subscription: $($context.Subscription.Name) ($subId)"

# 1. Verify budgets exist and have notification thresholds configured
Write-Output "`n[1] Checking configured budgets..."
$budgets = Get-AzConsumptionBudget -Scope "/subscriptions/$subId" -ErrorAction SilentlyContinue
if (-not $budgets) {
    Write-Output "[!] WARNING: No consumption budgets configured at subscription scope."
    Write-Output "    Create one: New-AzConsumptionBudget -Name 'AI-Workload-Budget' -Amount 5000 -Category Cost -TimeGrain Monthly"
} else {
    foreach ($b in $budgets) {
        $notifyCount = if ($b.Notification) { $b.Notification.Count } else { 0 }
        Write-Output "    Budget: $($b.Name) | Amount: $($b.Amount) | Notifications: $notifyCount"
        if ($notifyCount -eq 0) {
            Write-Output "    [!] Budget '$($b.Name)' has NO alert notifications — it will not warn anyone."
        }
    }
}

# 2. Verify action groups exist for alerting
Write-Output "`n[2] Checking action groups (alert delivery paths)..."
$actionGroups = Get-AzActionGroup -ErrorAction SilentlyContinue
if (-not $actionGroups) {
    Write-Output "[!] WARNING: No action groups configured. Budget alerts have nowhere to go."
} else {
    $actionGroups | ForEach-Object { Write-Output "    Action Group: $($_.Name) in $($_.ResourceGroupName)" }
}

# 3. Inventory Azure OpenAI / Cognitive Services deployments
Write-Output "`n[3] Inventorying AI service deployments..."
$aiResources = Get-AzResource | Where-Object { $_.ResourceType -match 'CognitiveServices|OpenAI|MachineLearning' }
if ($aiResources) {
    $aiResources | ForEach-Object {
        Write-Output "    $($_.ResourceType) | $($_.Name) | RG: $($_.ResourceGroupName) | $($_.Location)"
    }
    Write-Output "    Total AI resources: $($aiResources.Count)"
    Write-Output "    ACTION: Verify each has per-deployment token rate limits (TPM/RPM) configured."
} else {
    Write-Output "    No Azure AI resources found in this subscription."
}

Write-Output "`n[*] Audit complete. Remediate any [!] findings before the next billing cycle."

For AWS Bedrock / Lambda-hosted agents, the equivalent guardrail check:

Bash / Shell
#!/bin/bash
# AI Consumption Guardrail Audit — AWS
# Verifies budgets, anomaly detection, and Bedrock invocation logging

set -euo pipefail
echo "[*] Auditing AWS account: $(aws sts get-caller-identity --query Account --output text)"

# 1. Verify budgets exist with notification thresholds
echo "[1] Checking AWS Budgets..."
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
BUDGETS=$(aws budgets describe-budgets --account-id "$ACCOUNT_ID" --query 'Budgets[].BudgetName' --output text 2>/dev/null || echo "")
if [ -z "$BUDGETS" ]; then
  echo "[!] WARNING: No AWS Budgets configured. Create one with notifications at 50/80/100/120% thresholds."
else
  echo "    Budgets found: $BUDGETS"
fi

# 2. Check Cost Anomaly Detection monitors
echo "[2] Checking Cost Anomaly Detection..."
MONITORS=$(aws ce get-anomaly-monitors --query 'AnomalyMonitors[].MonitorName' --output text 2>/dev/null || echo "")
if [ -z "$MONITORS" ]; then
  echo "[!] WARNING: No cost anomaly monitors. Runaway agent spend won't be flagged until the invoice."
else
  echo "    Anomaly monitors: $MONITORS"
fi

# 3. Verify Bedrock invocation logging is enabled (needed for per-model consumption forensics)
echo "[3] Checking Bedrock model invocation logging..."
for REGION in us-east-1 us-west-2; do
  LOGGING=$(aws bedrock get-model-invocation-logging-configuration --region "$REGION" --query 'loggingConfig.s3Config.bucketName' --output text 2>/dev/null || echo "")
  if [ -z "$LOGGING" ] || [ "$LOGGING" = "None" ]; then
    echo "    [!] $REGION: Invocation logging NOT enabled — you cannot forensically reconstruct consumption events."
  else
    echo "    $REGION: Logging to s3://$LOGGING"
  fi
done

echo "[*] Audit complete."

Remediation: Building Actual Guardrails

Detection tells you the house is on fire. These controls stop the fire from starting:

1. Hard per-identity and per-agent rate limits — enforced, not alerted. Configure token-per-minute (TPM) and request-per-minute (RPM) caps at the gateway or provider level for every agent identity. Azure OpenAI supports per-deployment TPM limits; Anthropic and OpenAI support workspace/project-level rate limits; API gateways (Kong, Apigee, AWS API Gateway) can enforce quotas per API key. An agent that hits its cap should be throttled, not billed.

2. Circuit breakers on agentic loops. Every agent framework deployment should enforce a maximum iteration count, maximum tool-call chain depth, and maximum session token budget at the orchestration layer. If your agent runtime doesn't support this natively, wrap it — a 200-iteration cap stops infinite loops cold. This is the single highest-value control for agentic recursion.

3. Kill-switch automation tied to spend anomalies. Budget alerts that email someone are too slow — a runaway agent at $40/minute burns $2,400 in the hour it takes someone to read the email. Wire anomaly detection (Azure Cost Anomaly Alerts, AWS Cost Anomaly Detection, or your own metering Lambda/Function) to automated actions: revoke the agent's API key, disable the deployment, or scale the service to zero.

4. Treat prompt injection as a cost attack vector. Inputs from untrusted sources (scraped web content, inbound email, user uploads) must be sanitized before reaching agents with tool-calling capability. Constrain agent tool scopes to least privilege: an agent that summarizes documents doesn't need the ability to call paid external APIs or provision infrastructure.

5. Separate billing boundaries for experimentation vs. production. Agent development workloads belong in isolated subscriptions/projects with small hard budget caps. No shared billing with production. No exceptions.

6. Enable invocation logging everywhere. Azure OpenAI diagnostic logs, Bedrock invocation logging, and proxy-level request logging are your forensic record for reconstructing what a runaway agent actually did. Without them, post-incident analysis is guesswork.

7. Add unbounded consumption to your threat model and IR runbooks. Map this to OWASP LLM06 (per the current OWASP Top 10 for LLM Applications ranking) in your application risk register, and give your SOC a documented response procedure for consumption events: confirm scope via the queries above, revoke the offending identity, snapshot invocation logs, then restore service with throttling in place.

Runaway AI spend is the rare incident class where the "attacker" is often your own architecture. The organizations that handle it well are the ones that treated cost controls as security controls before the invoice arrived.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.