Table of Contents
Share this entry
Privilege escalation using non-person identities in AWS is nothing new. EC2 instance roles and Lambda execution roles are well understood to be mechanisms for bad actors to elevate their own privileges if not locked down properly. What’s less well understood is the concept of AI-centric identities – how agentic workflows gain the privileges to perform their tasks, and how permissions assigned to these workflows using existing IAM infrastructure can introduce risk.
In this blog, we’ll investigate Bedrock AgentCore Code Interpreters, and how this tool designed for agent use can be abused to gain access to new IAM roles.
Bedrock AgentCore Code Interpreters
On July 16th, AWS released their preview version of Bedrock AgentCore. As a whole, this service is a collection of tools meant to assist in deploying and scaling AI agents. On top of being able to define agents using ECR images, this service provides the ability to define agentic tools independently from the agents themselves.
One type of built-in tool is the AgentCore Code Interpreter, which provides agents with an environment in which they can execute code. AWS frames code interpreters as tools for agents:
“The Amazon Bedrock AgentCore Code Interpreter enables AI agents to write and execute code securely in sandbox environments, enhancing their accuracy and expanding their ability to solve complex end-to-end tasks. This is critical in Agentic AI applications where the agents may execute arbitrary code that can lead to data compromise or security risks. The AgentCore Code Interpreter tool provides secure code execution, which helps you avoid running into these issues.”
Code Interpreter Access Control
To make these dynamic, Code Interpreters exist as their own resources that can be invoked using IAM permissions – specifically `bedrock-agentcore:InvokeCodeInterpreter`. They can be invoked by AgentCore agent runtimes directly using the AgentCore SDK (obtaining permissions via the agent runtime execution role), but it can also be invoked outside of the agent entirely by hitting the AWS control plane. As such, non-agent identities can also invoke these Code Interpreters.
Invoking Code Interpreters
There’s no AWS CLI command for invoking Code Interpreters, but it is fairly easy to accomplish in Python using boto3 to set up a session, then calling the `invoke_code_interpreter()` function. The caller provides arbitrary code, which then gets run in the code interpreter’s environment.
For example, running bash commands using the default AWS-managed Code Interpreter can be accomplished with just the `bedrock-agentcore:StartCodeInterpreterSession` and `bedrock-agentcore:InvokeCodeInterpreter` permissions:
AWS Control Plane Access
One noteworthy feature of the default code interpreter environment is that it comes with the AWS command line tool installed by default – though it is not configured with any credentials:
Custom Code Interpreters
It would be one thing if the default code interpreter was the only one available. Agents could supply their own credentials in the supplied code and invoke the AWS CLI in the Code Interpreter using their own runtime’s execution role, and that would be that. AWS however lets you create custom code interpreters, and supply them with their own execution role.
The AWS Docs illustrate how this can be done to enable integration with other resources like S3. By invoking this code interpreter via in the same way we did the default one, we can confirm that the AWS credentials in the code interpreter environment are set to the configured role.
Tool Configuration: Public VS Sandbox
If the tool configuration has the code interpreter set to “Public”, we can perform any AWS control plane action the code interpreter execution role has access to. As seen in the screenshot above, we can access the STS regional endpoint to get information about the Code Interpreter credentials.
It’s easy to assume that if the tool configuration were instead set to ”Sandbox”, that we would lose access to AWS resources using the code interpreter’s execution role. This however is only partially true; while calls to many AWS regional endpoints will indeed fail, several S3 operations do still go through.
The Summary So Far
So what does this all mean? If you have custom Code Interpreters in AgentCore with their own execution roles, anyone with the ability to invoke them can effectively assume those execution roles by directly calling the code interpreters and instructing them to perform control plane actions.
Closing the Privilege Escalation Path
It’s clear that in an account where AgentCore is being used, care must be taken to ensure that only authorized access to privileged Code Interpreters is permitted. Confusingly, many of the common methods to lock down privileged resources and monitor for their misuse are either unavailable or require more effort than normal to configure appropriately.
Resource Policies are a No-Go
One common method to lock down access to highly privileged resources (KMS keys, Lambda Functions, IAM Roles, etc.) is to use resource policies to control access to individual resources. When a sensitive resource is created, it’s much easier to explicitly define which identities can access it in one place, rather than go through every identity-based policy in the cloud and ensure no unintended access to the resource is granted.
A similar solution would be ideal for Code Interpreters. For example, if a custom Code Interpreter is set up with an execution role that grants it access to sensitive S3 data that only a single agent type needs access, the ability to create a resource policy on that code interpreter limiting access to just the agent runtime role that needs access would be the most precise solution.
Despite this, AWS has for some reason decided to not support resource policies in any part of Bedrock AgentCore:
Cloudtrail Monitoring Requires Some Extra Configuration
On top of proactive access control using resource policies, auditing actual Code Interpreter invocations provides proof that access control measures are being enforced correctly. Monitoring Cloudtrail for these events can be an effective way to enact this.
One thing that’s important to note about this approach is that logging invocations of Code Interpreters does not occur by default in Cloudtrail. Code interpreter invocations logs are considered Data Events – meaning that you need to manually enable them, and that AWS will charge for their storage.
By enabling Data Event logging and auditing the `InvokeCodeInterpreter` event, you can catch attempts to leverage code interpreter privileges by unauthorized individuals.
For an extra level of insight, monitoring can also be configured for the `CreateCodeInterpreter` management event – which is logged by default in Cloudtrail, catching attempts to set up Code Interpreters with wide-ranging permissions that can later be invoked.
This gives warning when a user with `iam:PassRole`, `bedrock-agentcore:CreateCodeInterpreter` and `bedrock-agentcore:InvokeCodeInterpreter` sets up a code interpreter with a privileged IAM role with the intent to pivot to it using the Code Interpreter.
Central Management With Service Control Policies
Without resource policies, the only centralized way to prevent unauthorized access to Code Interpreters is using Service Control Policies (SCPs). For privileged Code Interpreters, SCP statements can be added that explicitly deny unintended access:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "bedrock-agentcore:InvokeCodeInterpreter",
"Resource": "arn:aws:bedrock-agentcore:<region>:<account>:code-interpreter-custom/<code interpreter id>",
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::<account>:role/<allowed agent role>"
}
}
}
]
}
The downside to the approach is that it needs to be implemented at the Org Management level rather than the resource level, meaning that your average developer creating custom Code Interpreters is not going to be able to perform this task themself.
Conclusion
The introduction of endpoints that run any and all provided code in the context of a privileged role presents a serious security risk if access to said resource is not tightly controlled. In the long run, I would like to see AWS enable resource policies for AgentCore resources. Controlling access at the organizational level using SCPs is cumbersome but necessary at this moment to prevent what is effectively an unlogged (by default) role assumption.
And as the one control mechanism that does work is cumbersome, it’s likely that in many cases, security will be set on the backburner as developers adopt this new tooling that enables them to perform their tasks more efficiently and at greater scale. The security of AI workloads and their tools relies on a solid implementation of Identity and Access Management. AWS has proven time and again that they can develop good solutions to this problem – but in the case of AgentCore Code Interpreters, something is missing.