AWS Bedrock AgentCore 執行角色權限收窄指南
One prompt shouldn't own your cloud: scoping AWS Bedrock AgentCore credentials
文章解説 Zenity Labs 的研究發現,AWS Bedrock AgentCore 的 IMDS 存取與過寬 IAM 角色可讓單一提示詞取得憑證,並影響同一 AWS 帳戶及區域內的其他智能體。
文章將 AgentCore 權限過寬與提示詞注入造成的憑證風險連結,並整理拆分執行角色、收窄權限及驗證設定的實務清單。
Start here: find out what your agent's execution role can actually do. If you run agents on AWS Bedrock AgentCore, run these two commands and read the permissions they return:
aws iam list-attached-role-policies --role-name <your-agentcore-exec-role>
aws iam list-role-policies --role-name <your-agentcore-exec-role>
If that role is the default AgentCore execution role, the output may list permissions that reach far beyond the one agent you deployed. That gap is not theoretical. In October 2026, a security research team showed that a single chat prompt to one exposed agent was enough to take over every Bedrock AgentCore agent in the same AWS account and region.
This post explains the finding in plain terms and gives you a checklist you can apply to your own role today. No new tools, no platform migration.
What actually happened
The research (Zenity Labs, published October 8, 2026, and presented at the SecTor 2026 conference) targeted AWS Bedrock AgentCore, Amazon's managed platform for running production agents. The team found two problems that stack on top of each other.
First, an agent running inside AgentCore could reach the instance metadata service (IMDS) at the link-local address 169.254.169.254. AgentCore runs each agent in a lightweight microVM that did not isolate network traffic the way a normal compute instance does. As a result, any agent tool that can make an HTTP request becomes a server-side request forgery primitive: a request it makes originates from inside the instance, so IMDS answers it with the temporary IAM credentials for the agent's own role. A carefully written prompt was all it took to make the agent fetch those credentials and hand them back.
Second, the default IAM role attached to AgentCore workloads was overprivileged. It was not scoped to a single agent. It carried broad permissions across every AgentCore resource in the account's region: invoking other agents, reading sessions, creating memories, and reading secrets from AWS Secrets Manager.
Put the two together and the blast radius is the whole region. One exposed agent plus one prompt equals the ability to:
- discover every other agent's ID, because the role allowed
DescribeLogGroupsacross the region; - invoke any agent in the region (
bedrock-agentcore:InvokeAgentRuntime), opening lateral movement to internal agents you never meant the first agent to reach; - read every private conversation across all agents and users (
bedrock-agentcore:ListEvents), breaking AgentCore's privacy boundary completely; - plant memories that permanently change another agent's behavior (
bedrock-agentcore:CreateEventonBedrockAgentCoreMemory), so a trusted enterprise agent keeps running under attacker-controlled instructions; - pull the credentials AgentCore was supposed to keep away from the agent (
secretsmanager:GetSecretValue,bedrock-agentcore:GetResourceApiKey).
The disclosure timeline matters for trust. The IMDS access was reported to AWS on December 25, 2025; AWS closed it as "informative" in April 2026 after moving newly deployed agents to IMDSv2. The overprivileged-role report was filed January 12, 2026; AWS confirmed substantial hardening of the default execution role on September 29, 2026. AWS's public position is that the behavior is "documented and expected": an agent can reach resources in another account only if the developer explicitly grants permissions on both sides. Their recommendation is unchanged and correct: grant execution roles only the permissions the agent needs.
One caveat for teams on existing deployments: AWS's September 2026 hardening changed the default for newly created roles. Agents deployed before that date may still carry the old broad role, because AWS does not retroactively rewrite a role you already attached. If your agent predates late September 2026, assume the role is still wide until you check it yourself with the commands above.
Why this is your Tuesday problem
You did not write AgentCore's default role. But you attached it, or accepted it, to your agent. The lesson is not "AWS is unsafe." The lesson is that an agent's credential scope is a product decision you own, and most teams set it once and never revisit it.
Agents are not web servers. A web server handles one request at a time and has no session to steer. An agent holds a session, calls tools, and can be redirected by content it fetches from the web, from a document, or from another agent. The same prompt injection that used to mean "the model said something wrong" now means "the model used your credentials." When the role is broad, one bad input becomes an account-wide event, not a contained mistake.
Consider a realistic case. Your support agent has a tool that queries an internal API. That API lives in the same account as a second agent that can read customer records and a third that can post to social channels. If all three share one broad role, a poisoned instruction to the support agent does not stop at the support API. It can pivot to the customer-records agent and then to the posting agent, because the shared role permits all of it. The fix is not smarter prompts. The fix is a narrower role.
Scope it down today
You do not need to wait for a platform fix. Four moves cut the blast radius now.
1. Give each agent its own role. Do not share one execution role across agents. Create a dedicated role per agent and attach only the permissions that agent's tools need. If agent A has no business reading agent B's memory, its role must not allow bedrock-agentcore:CreateEvent on shared memory.
2. Apply least privilege to the letter. Start from an empty policy and add one permission per tool call you can name. If you cannot name the call, the agent should not hold the permission. Review DescribeLogGroups and secretsmanager:GetSecretValue first; those are the two that turn a local leak into a regional one.
3. Keep secrets out of the agent's own role. Store third-party credentials in AWS Secrets Manager and let AgentCore Gateway broker them per tool. The agent's execution role should not hold secretsmanager:GetSecretValue for secrets it only reaches through a gateway.
4. Force IMDSv2 and block the metadata path. Launch agents with IMDSv2 only, which requires a token instead of an open PUT. Where your runtime allows it, deny outbound access to 169.254.169.254 from the agent's execution environment, so a tool cannot reach metadata even if it is prompted to.
A minimal least-privilege role for a single read-only agent looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["bedrock-agentcore:InvokeAgentRuntime"],
"Resource": "arn:aws:bedrock-agentcore:<region>:<account>:agent/<this-agent-id>"
}
]
}
No DescribeLogGroups. No secretsmanager:*. No *:* anywhere. Add one statement per tool, scoped to that tool's exact resource.
Verify the fix
After you tighten the role, prove it. Re-run the two aws iam commands from the top and grep the output for *:* and for any bedrock-agentcore:* permission scoped wider than this one agent. Then run a deliberate negative test: from inside the agent, try to call an action the new role should deny, and confirm it fails. If the agent can still list other agents or read secrets, the role is still too wide.
Make this a recurring check, not a one-time cleanup. Add the two aws iam commands to a scheduled job or a CI step that fails when a role grows wider than its declared tools. Credential scope drifts as agents gain features, so the check has to run as often as the agents change.
Treat the agent's IAM role as part of the agent's spec, not as platform boilerplate. Name the tools, name the permissions each tool needs, and review them on the same cadence as you review the agent's prompts. One prompt should never own your cloud; the role you attach decides whether it can.
This post was written with AI assistance. The author is responsible for its content.
來源:DEV Community · dev.to