agent-blast
What can a hijacked AI agent reach in your AWS account, and can you prove it?
cloud-audit scan # discovers agents, their tools and identities
cloud-audit agent-blast # every agent, both threat models, offline
cloud-audit agent-blast -a support-bot # one agent (name, id or ARN substring)
cloud-audit agent-blast --verify # add IAM policy-simulator proof (read-only)
cloud-audit agent-blast --demo # the built-in sample, no AWS needed
The question
An AI agent in AWS is not one identity. It is a bundle:
- the role the agent runs as (Bedrock Agent resource role, AgentCore runtime role, gateway role),
- the execution roles of the Lambda functions behind its tools (action groups, gateway targets),
- the roles of its knowledge bases, code interpreters and browsers.
When the agent is hijacked, the attacker acts with those identities. Which ones, and how far they
reach, depends on how it was hijacked. agent-blast answers per agent under two threat models.
| Threat model | What the attacker has | Reach |
|---|---|---|
| Identity takeover | credentials of a role the agent runs as: code-interpreter escape, metadata-service read, leaked session | the full role: privilege-escalation methods, AssumeRole hops through the trust graph, data |
| Behaviour takeover | nothing but a prompt: indirect prompt injection through a document, ticket, email or web page the agent reads | what the agent's tools can do, bounded by the tools' own execution roles |
The distinction matters. A prompt-injected agent never sees a credential; it can only call the tools
it has, and each tool executes under its role. That role is an upper bound: what the tool's code
does with its parameters is narrower, and IAM cannot tell you that. agent-blast reports the bound
and says so.
What it reads
All calls are list/get, read-only, with no per-call charge. They run during scan; agent-blast
itself works on the saved report and makes no AWS calls unless you pass --verify.
Bedrock Agents (bedrock-agent)
GetAgent: the agent resource role, foundation model, guardrail configuration, status.ListAgentActionGroups/GetAgentActionGroupat theDRAFTversion: each action group's Lambda executor (orRETURN_CONTROL), its OpenAPI or function schema size, its state.GetFunctionConfigurationon each executor Lambda: the tool's execution role.ListAgentKnowledgeBases/GetKnowledgeBase/ListDataSources/GetDataSource: the knowledge base role and the S3 buckets it ingests.
AgentCore (bedrock-agentcore-control)
- Runtimes: role, network mode, inbound authorizer.
- Gateways: role, inbound authorizer type, policy engine and mode, and every target with its kind
(Lambda, remote MCP server, API Gateway, OpenAPI, Smithy) and credential provider type. A Lambda
target resolves to its execution role; a
GATEWAY_IAM_ROLEcredential provider means the gateway's own role calls the backend; OAuth or API-key targets have no IAM identity and are reported as not assessed. - Code interpreters and browsers: execution role and network mode.
IAM policies of exactly those identities: inline, attached managed, and (for users) group
policies, kept raw as (action, resource, effect, condition-present, source). NotAction and
NotResource statements are recorded with an explicit prefix so "everything except X" is never
mistaken for "X". Conditions are flagged, not evaluated statically. The simulator decides.
What it computes
For every identity (own roles under identity takeover, tool roles under behaviour takeover):
- Blast radius: the same forward BFS as
cloud-audit blast-radius, seeded with the role: the 64 privilege-escalation methods, lateral AssumeRole hops, admin impact. - Reach: every policy grant matched against a catalogue of data-plane actions, in this order:
secrets (Secrets Manager, SSM parameters, KMS decrypt), knowledge-base writes (RAG poisoning),
lateral movement (
sts:AssumeRole), code execution (Lambda invoke and code update, AgentCore code interpreter), S3 writes, data reads (S3, DynamoDB, RDS Data API, SQS), model invocation. A hardDenyremoves a reach; a conditionalDenyis noted; a conditionalAllowis flagged. - Knowledge-base buckets are always concrete targets, even when the grant is
s3:*on*, and every agent's bucket counts: a gateway tool that can write into another agent's knowledge base is cross-agent RAG poisoning. - Tags: OWASP Top 10 for Agentic Applications (2026) codes and MITRE ATLAS (v2026.08) technique ids, per reach and per agent.
- Coverage notes: a region the inventory was denied, a tool with no IAM identity, a principal with no policy data in the scan. Never a silent pass.
The headline picks the worst thing first: admin escalation from an own role, then from a tool role, then knowledge-base poisoning, then counts of secret, data and lateral reach.
Sample output
support-bot (bedrock_agent, eu-central-1)
├── A hijacked tool (tool: create-ticket) can escalate to account admin via PassRole+Lambda
├── status: PREPARED
├── Identity takeover (attacker holds the role's credentials)
│ └── support-bot-agent-role arn:aws:iam::123456789012:role/support-bot-agent-role
│ └── no escalation path; 3 reach(es) from policy grants, 1 on named resources (see Reach)
├── Behaviour takeover (prompt injection: the agent's tools, their roles)
│ ├── search-docs action_group_lambda -> support-bot-search-role
│ │ └── no escalation path; 4 reach(es) from policy grants, 4 on named resources (see Reach)
│ ├── create-ticket action_group_lambda -> support-bot-ticket-role
│ │ ├── reaches Account Takeover in 1 hop(s) via PassRole+Lambda (risk 72/100)
│ │ └── escalation: PassRole+Lambda
│ └── product-docs knowledge_base -> support-bot-kb-role
├── Reach (13 action/resource pairs)
│ ├── tool: search-docs secretsmanager:GetSecretValue on
│ │ arn:aws:secretsmanager:eu-central-1:123456789012:secret:prod/db-credentials-Ab12Cd
│ │ unverified read secret values
│ ├── tool: create-ticket sts:AssumeRole on arn:aws:iam::123456789012:role/ops-admin unverified
│ │ assume IAM roles
│ ...
├── Tags
│ ├── OWASP Agentic: ASI02 Tool Misuse and Exploitation, ASI03 Identity and Privilege Abuse,
│ │ ASI05 Unexpected Code Execution
│ └── MITRE ATLAS: AML.T0034 Cost Harvesting, AML.T0040 AI Model Inference API Access, AML.T0053
│ AI Agent Tool Invocation, AML.T0086 Exfiltration via AI Agent Tool Invocation
└── Simulated, not executed: ...
Run cloud-audit agent-blast --demo for the full sample, including an AgentCore gateway whose
Lambda target can poison another agent's knowledge base.
Proof Mode for agents
--verify asks iam:SimulatePrincipalPolicy about every concrete (principal, action, resource)
reach and every escalation path of the agent's identities. The request carries the context an
attacker holding the credentials really has: no MFA on the session, TLS transport. Each reach is then
marked:
- PROVEN (
allowed): the simulator allowed the action on that resource. - DENIED: the simulator denied it, and the line names the layer when the simulator reports it (an SCP, the permissions boundary). The static reach was a false positive.
- not asserted: incomplete result, an unevaluated condition key (named), or a wildcard reach that no concrete ARN can be named for.
A bucket-wide grant is proven on a synthetic object key inside the bucket; the simulator accepts resources that do not exist. See Proof Mode for what the simulator does and does not evaluate.
Honest limits
- Tool reach is an upper bound. The tool's role is what IAM allows the tool's code; what the code does with a prompt-controlled parameter is narrower. Reading the code, or a declared mapping from parameters to resources, is out of scope for a read-only scanner.
- Simulated, not executed. A
PROVENline proves the permission exists under identity policies, the attached permissions boundary and SCPs. Resource-based policies of the targets, RCPs and VPC endpoint policies are not evaluated by the simulator for IAM roles. - Runtime is out of scope. Whether a given prompt actually steers the agent, what a guardrail would block, and what the agent did last Tuesday are runtime questions for runtime tools.
- DRAFT version. Bedrock Agents are read at their working version. An alias pinned to an older numbered version may differ; that is a drift question, not an identity one.
- Bedrock Agents first, AgentCore Gateway second. The agent-to-tool binding is explicit in the Bedrock Agents API. AgentCore runtimes call gateways from their code, so a runtime and a gateway are reported as separate agents; which runtime uses which gateway is not visible from the control plane.
Output formats and integration
cloud-audit agent-blast --format json -o agents.json # every agent, full model incl. blast graphs
cloud-audit agent-blast --format markdown -o agents.md # review-ready tables
cloud-audit agent-blast -a planner --max-depth 3 # smaller graphs
The MCP server exposes the same report through the get_agent_blast tool, so an assistant can ask
"what could my agents reach if hijacked" against the last scan.
Related checks
Configuration findings for the same surface come from the AgentCore checks
(aws-agc-001 to aws-agc-006) and the AI-SPM checks for Bedrock and SageMaker.
agent-blast is not a check: it does not fail a scan, it explains what a failure would cost.