- A researcher ran system commands inside the sandbox behind AWS's MCP Server script tool, using Python's match/case feature to slip past both protection layers.
- The recovered credentials belong to an AWS-owned account and were denied every API call except an identity check. In the researcher's testing, no other customer's data was reachable.
- The report was marked resolved on October 23, 2026. Ask vendors how agent sandboxes were tested and what the sandbox's own credentials can do.
AI agents now run code on cloud accounts
AWS made its MCP Server generally available on May 6, 2026. MCP, short for Model Context Protocol, is a standard in which a server offers tools and an AI agent calls them. According to the researcher, assistants such as Claude Code, Kiro and Cursor can connect to it. Through it they can look up current AWS documentation and act on an account using IAM credentials the user supplies.
One tool, called aws___run_script, accepts a short Python script and runs it on AWS's side. It lets an agent bundle several API calls into one request. AWS runs the script in an AWS Lambda sandbox that restricts imports, built-in functions, attribute access and file operations.
A researcher who publishes as xplo1t-sec, working with Claude Opus 4.6, tested what those limits really stopped. The lesson of the result is simple. A sandbox is only as strong as the list of tricks its builders thought to block.
Two layers, and a gap in each
The sandbox had two layers. The first was a static validator. It read the structure of the submitted code and rejected risky operations, such as reading obj.__class__ or calling getattr(). The second worked while the code ran. It swapped Python's built-in type() for a stand-in called _safe_type(), which returns restricted proxy classes.
The researcher found a way past both. Python 3.10 added match/case. A class pattern checks an object's type, then reads attributes from it. The attributes it reads come from a list named __match_args__ on the class. Python itself performs that lookup while the pattern runs, so the blocked name never appears in the code at the moment of the read.
The attack rested on two facts. First, the validator let code assign to __match_args__. It compared assignments with a short list of banned double-underscore names, and __match_args__ was missing from that list. Second, the hidden reads still happened. The researcher says the check lives inside CPython, the standard Python engine, so neither the validator nor the replaced functions could stop it.
The validator did reject dunder names written as plain strings. The researcher built each name at runtime with chr(), which the validator could not see. So the pattern itself hides the read, and chr() hid the names.
How the chain worked
The researcher started with collections.namedtuple(), which the sandbox allowed. It gave a class whose __match_args__ could be changed. Pointing it at __reduce_ex__, a method used by Python's pickle serialization, and calling it with protocol 4 returned a pickle recipe. The recipe's first element was copyreg.__newobj__, a real standard-library function rather than a proxy.
Real functions carry __globals__, a dictionary of names from the module where they were defined. For this function it included the original __builtins__ dictionary. That holds __import__, which can load the os and subprocess modules.
Reading __globals__ needed one more step. The real function type cannot be modified. But _safe_type() tries to subclass the real type, and Python does not allow that for functions. So it fell back to building a new proxy class, and that class could be changed.
The researcher set the proxy's __match_args__ to __globals__. The proxy also said copyreg.__newobj__ was a function, so the pattern matched. The researcher says the validator missed the hidden reads and the runtime proxy supplied the missing piece. The exploit needed a gap in each layer. One layer did not cover for the other.
What was reached, and what was not
Running id showed command execution as the Lambda user. Running env exposed the Lambda execution role's credentials. The researcher could also read files, including the sandbox's own source code. As in an ordinary Lambda function, the main filesystem could not be written to, but the /tmp folder could.
The researcher confirmed through sts:GetCallerIdentity that the credentials belong to a role in an AWS-owned account, not a customer account. Every AWS API call the researcher tried was refused with an explicit deny, apart from sts:GetCallerIdentity. That one call is always available and needs no permissions.
The researcher reports finding no route to other sessions or customer data. The escape stayed inside the Lambda container created for the researcher's own session. The researcher credits other controls with limiting the damage: locked-down credentials, no internet access and, in their testing, a separate container per session.
The disclosure timeline
The researcher reported the issue to Amazon's AWS vulnerability disclosure program through HackerOne on July 26, 2026. HackerOne validated the report and forwarded it to the AWS team on July 30. On September 15, the AWS team acknowledged it and confirmed a fix was in progress. The report was marked resolved on October 23, 2026. The post does not describe the fix itself.
What the case shows
The researcher's own conclusion is that Python often offers several ways to do the same thing. Blocking the obvious ones can leave a quieter one open. A replacement built-in can also backfire if it behaves differently from the original. A defender must close every path, while an attacker needs one.
This is an argument for outside testing. The source does not say how AWS tested the sandbox before launch. It does show that two layers of defence both had a gap, and that a researcher outside AWS found the path through them. As agents gain permission to run code against live cloud accounts, the sandbox does real security work. Here, by the researcher's account, other controls kept the damage small.
Questions to put to your team
Ask each vendor whether the sandbox behind its agent code tools has had independent security testing. Ask what credentials the sandbox itself holds and what they are allowed to do. In this case they were denied everything but an identity check.
Ask what happens if a session's sandbox is breached. Does it reach other customers, or only its own container, as the researcher found in this case? Ask the vendor to confirm what its fix changed. And ask whether your team logs what AI agents actually execute, not only what they may request.
Produced by the WebPulse Newsroom with AI assistance from the original reporting credited below, and checked against that source by our editorial review. How we use AI.
Original reporting: xplo1t-sec.github.io.





