The Vault Kept the Secret. The Agent’s Shell Read It Anyway.
The credential was encrypted at rest, encrypted in transit, sealed behind KMS keys and gated by IAM. It still ended up on an attacker’s webhook.
On 18 September 2026, Unit 42 published research on AWS AgentCore Harness, Amazon’s managed runtime for AI agents. Working in a test deployment, the researchers showed how a prompt injection hidden in a support ticket could steer an agent into using its built-in shell tool to recover a downstream service credential from the harness’s own runtime memory, send it out, and replay it from a laptop against an MCP server holding customer data.
Nothing in the vault was broken. That is the point.
A vault protects a secret while it is stored and while it travels. The moment an agent runtime actually uses that secret, it has to exist in plaintext somewhere. If the agent’s own tools can reach that somewhere, an injection that reaches the tools can reach the secret.
This is a demonstrated configuration risk, not a claim that every AgentCore deployment is compromised. AWS reviewed the report and closed it as informative under its shared responsibility model, pointing to tool scoping and egress filtering as customer-side controls. Those controls exist and they work. The research is a reminder that defaults decide what most people actually run.
1. The support-ticket test
Unit 42 built a fictional operator, SupportCo, running a customer-support agent on AgentCore Harness. The agent read inbound tickets, looked up account records through an authenticated downstream MCP server and replied to whoever wrote in. The researchers describe it as a default-configuration deployment: a managed harness, the built-in shell tool, and an MCP integration whose bearer token lived in AgentCore Identity and was referenced by ARN, as the documentation shows.
Their path in was ordinary. Directly asking a well-aligned model to run reconnaissance commands produced refusals. Because the harness allows the model to be chosen per invocation, they switched to a more permissive model that supported tool calling. Hand-typed shell syntax still drifted, so they stopped asking the model to reproduce commands and instead placed one short instruction inside a hidden HTML comment in a support ticket. The agent read the ticket, called its shell tool, and the researchers’ code ran inside the harness.
From there, the findings stacked up:
- The shell tool ran as root inside the harness.
- It ran under the same user as the harness runtime process itself.
- That runtime process’s memory was readable from the shell.
- The runtime resolved the vault reference into the real token in that memory, because it needed the token to call the MCP server.
A scan of that memory recovered the token and the MCP server address. Both left the harness in a single outbound request. Replayed from outside AWS, with no AWS credentials, the token let the researchers list the MCP tools, look up customer records containing personal data and create a ticket.
2. Why vault protection ends at runtime use
It is tempting to read this as a vault failure. It is not. The vault did what vaults do.
Unit 42’s own conclusion is the useful one: vaults protect at rest and in transit, not in use. Any credential the harness resolves at runtime has to become plaintext to be useful. Protecting it while in use is a separate problem, and storage encryption does not solve it.
The credential that leaked also matters. It was not the end user’s session. The person who sent the ticket was only allowed to invoke the harness. The vault held the operator’s service account for the downstream integration, wired in once at harness creation and reused across every session. The injection did not escalate the caller’s privileges; it borrowed the harness’s.
That is the pattern to watch for in any agent platform:
- The caller is authorised to ask.
- The runtime is authorised to reach.
- Untrusted content decides what the runtime does next.
When all three sit in one process, a ticket can do what its author never could.
3. How a default shell expands an injection’s reach
Before agents had shells, a successful prompt injection mostly changed what the model said, which typed tool it selected or what it leaked back in its answer. Still bad, but bounded by text output and the specific tools the developer chose to expose.
A general-purpose shell removes that bound. Programmatic tool use is genuinely valuable: agents write scripts instead of making dozens of round-trips, and they save context and latency. It also means the limit on an injection is no longer a typed schema. As Unit 42 puts it, whatever the shell tool can touch, an injection can touch: the file system, the process space, the network and any credential reachable from that environment.
AWS’s documentation is explicit about the defaults. The built-in shell and file_operations tools are available in every session unless restricted with allowedTools; if that parameter is omitted, all tools are allowed. The researchers add that the parameter scopes tool selection at invocation time rather than at harness creation, which makes it flexible if you know about it and easy to miss if you do not.
AWS also notes that allowedTools does not govern its separate direct command execution API, which has its own IAM permission. If you do not want commands run directly on the runtime, do not grant that permission.
The model’s judgement is not the boundary. In the test, a careful model refused and a permissive one complied. If the platform lets the model be swapped per invocation, model alignment cannot be the control that keeps credentials safe.
4. Tool scoping, least privilege and egress controls
Unit 42’s recommendations for AgentCore operators are short and practical. They generalise well to any agent runtime.
Scope tools per invocation. Set allowedTools on every invoke to what that session actually needs. A support agent answering tickets rarely needs a root shell. Sessions that do not call for the built-in tools should not get them.
Shrink every service credential. Scope each vault-held service account to least privilege for its one downstream integration. A leaked credential is worth exactly what its scope buys. Prefer short-lived, narrowly scoped tokens over long-lived operator accounts.
Watch and restrict egress. Monitor outbound traffic from harness containers. Unit 42 makes a sharp point here: any destination that is not on your downstream integration list is evidence of an active injection, not configuration drift. Default-deny egress turns a stolen secret into a stranded one.
Separate the resolver from the tools. For platform builders, the structural fix is isolation: credentials should be resolved somewhere the shell cannot read, or the shell should run in a sandbox isolated from the process that resolves them. Tools that run as the same user as the runtime share its secrets.
Treat untrusted content as untrusted all the way down. Support tickets, emails, web pages, retrieved documents and tool output are data. A hidden HTML comment should not be able to choose the next shell command.
5. Where ShieldCortex helps — and where it does not
Be clear about the shape of this problem first. ShieldCortex is not a vault, not a runtime isolation layer and not a universal shell gate. It cannot stop a process that runs as root from reading memory in its own sandbox, and it does not replace allowedTools, least-privilege service accounts or egress controls. Those are the primary fixes here, and they belong to the platform and the operator.
Its fit is earlier in the chain: the content that steers the agent and, where the host lets us, the action that follows.
- Content boundary. The attack started as hidden instructions in a support ticket. ShieldCortex scans untrusted content and agent memory writes at supported integration points for prompt-injection and credential-handling patterns, so poisoned material is flagged before it is retained or relied on.
- Action boundary. On hosts that expose a tool hook that can actually deny, a gate can hold a proposed shell or outbound action for policy or human approval. Action Guard stays off by default; where it is not wired, we do not pretend it is.
- Evidence. Keeping source and context signals beside tool decisions helps answer the question an incident review will ask: what did the agent read just before it did that?
Native agent memory stays the brain. We sit on the door. Defence still comes in layers:
- Vaults protect secrets at rest and in transit.
- Runtime isolation keeps tools away from resolved secrets.
- Per-invocation tool scoping limits what an injection can call.
- Least-privilege service accounts limit what a leak is worth.
- Egress controls limit where a secret can go.
- Content scanning and action gates make injected instructions harder to act on.
The vault kept the secret. The runtime handed it to a shell. Decide which tools each session really needs before an attacker decides for you.
A vault is not a sandbox.
Scope tools per session. Shrink service accounts. Watch egress. Scan the content that steers the agent, and gate the actions your host lets you gate.
See ShieldCortex optionsSources
- Unit 42 — A Vault with a Heap-View: The Uncomfortable Space Between AgentCore Harness and Identity (18 September 2026)
- AWS — Amazon Bedrock AgentCore Developer Guide: Tools (default tools and
allowedTools)