AgentCore Security
Amazon Bedrock AgentCore Session Isolation: Security Tests
AgentCore Runtime Instances validates a supplied runtimeSessionId's format but does not verify that it belongs to the invoking identity. This guide turns that behavior into a two-user session-swap test, expected denials, and a CloudTrail investigation for shared-principal backends.
TL;DR (October 2026):
- AgentCore checks the format of a Runtime Instances session ID, not whether the caller owns that session.
- In a multi-user app that invokes through one IAM role, the application must map the authenticated user to server-controlled session IDs.
- Agents sharing an Instances host also share its filesystem. A container boundary or process boundary on that same host does not isolate mutually untrusted agents.
- For a sensitive deployment, test both the request path and the data path: identity at invocation, filesystem access inside the session, downstream credentials, and audit evidence.
The security question for an agent runtime is not just whether a request has a valid AWS signature or JWT. It is whether the identity that passed authentication is allowed to reach the particular conversation state, files, tools, and downstream credentials selected for that request. A runtime can correctly authenticate your backend and still receive a session identifier that the backend should never have used for this user.
Scope: Runtime Instances have a different isolation model
AgentCore has more than one runtime compute model. This article covers the Runtime Instances compute type, where AWS-managed EC2 instances run in your AWS account through a capacity provider. It does not generalize the Instances-specific findings to every AgentCore runtime. The serverless microVM model has a separate isolation architecture and its own controls. Check the compute type configured for your runtime before applying this test plan.
On Runtime Instances, AWS describes a session as the isolation unit and routes a session to an EC2 instance. The same session ID under different capacity providers represents different sessions. A session can retain state when it is stopped and resumed, so a stable identifier has operational value. That also means the identifier becomes security-sensitive wherever it selects user-owned state.
AWS's current security guidance makes the ownership boundary explicit: a caller supplies runtimeSessionId, and AgentCore validates its format but does not verify that the ID belongs to the caller. The invocation permission applies to the runtime resource, not to individual end-user sessions. If your API accepts a session ID from a browser and passes it through unchanged, you have delegated a tenant boundary to an untrusted parameter.
What authentication proves, and what it does not
Inbound authentication answers who may invoke the runtime endpoint. IAM SigV4 identifies an AWS principal. JWT authentication can identify a user through an issuer and claims. Neither fact automatically proves that a particular session ID belongs to that person. Your backend must connect the verified identity to the selected session before it calls AgentCore.
Keep the identities distinct in design documents and logs:
- End-user identity: the person or tenant authenticated by your application or identity provider.
- Invoker identity: the IAM role or user that signs the AgentCore request. In many web apps, this is a shared backend role.
- Runtime session: the server-side conversation and state key selected for the current user and purpose.
- Downstream identity: the credentials used when an agent accesses a database, repository, ticketing service, or other API.
A secure design records the verified end-user identity, the service principal, and the selected session as separate values. Do not use one of them as a substitute for another. For example, a session ID that contains a user email is still not proof of ownership. It is a label that may leak personal information and may be guessable.
Enforce session-to-user binding in the application
Store the mapping between a verified user or tenant and the session IDs it owns. Resolve the mapping after authentication, on the server. If a request includes a client-side conversation handle, look it up as an opaque application identifier and confirm that the authenticated principal has access before retrieving the AgentCore session ID. Do not let the client choose an arbitrary runtimeSessionId.
For shared-principal deployments, this mapping is the critical access-control check. A robust implementation checks ownership at every relevant boundary: when creating a session, when resuming it, when loading attached history or files, when invoking the runtime, and when returning the response. If a user is removed from a tenant or loses permission to a project, decide whether existing sessions are revoked, archived, or still available under a narrower policy.
Use unpredictable identifiers to reduce accidental discovery, but do not treat randomness as authorization. A UUID that an attacker obtains from a browser log, a support ticket, a referrer, or a leaked URL is still a valid session selector unless the backend checks ownership. Bind the mapping to a stable internal user or tenant key, and make the lookup fail closed when the session record is absent, disabled, or owned by a different tenant.
AWS recommends distinct IAM principals per end user or tenant group for high-security multi-tenant deployments where that architecture is practical. This reduces reliance on one shared backend identity and can let IAM policy constrain which runtime resources a principal may invoke. It does not remove the need to test your application mapping, data ownership, and downstream authorization. IAM can enforce only the boundaries expressed in the roles and policies you actually deploy.
Shared filesystems and agents on the same instance
Runtime Instances can run multiple agents on the same EC2 instance. AWS documents that these agents share a filesystem and that neither containers nor separate processes provide a security boundary between workloads on the same instance. Treat co-resident agents as mutually trusted. If one agent processes untrusted input or code, do not assume a container alone makes it safe to place it beside an agent holding more sensitive files or credentials.
Test the filesystem paths that hold transcripts, uploaded files, tool output, caches, temporary files, and generated artifacts. Check permissions at creation time and after a session resumes. Look for filenames derived from user input, predictable tenant directories, symlinks that escape an intended root, and logs that include secrets. Also check whether shared libraries or working directories are writable by a less trusted agent.
Persistent storage changes the lifecycle question. A session may stop and later resume with state intact, so logout in your product does not automatically mean the session data has been deleted. Define retention and deletion behavior, then verify it through the service API and the application record. A stale mapping should not become a way to reopen a session after a user loses access.
Credentials and downstream access
Separate the runtime execution role from credentials representing an end user. A broad execution role that can read every tenant's data turns a prompt injection or tool bug into a cross-tenant incident. Scope the role to the minimum AWS actions, resources, and secrets the agent needs. Where the agent acts for a user, use a user-delegated flow or a properly scoped token exchange rather than silently substituting an organization-wide credential.
AWS distinguishes JWT-based user identification from a user ID value supplied through a header. Its guidance says the user-ID path treats the identifier as an opaque string without validating it with an identity provider. Derive any such value from authenticated context on the server; do not copy it from a request header or JSON field supplied by the caller. Test issuer, audience, signature, expiry, and required claims on JWT paths, and test that downstream tokens are intended for the target resource.
Run a credential inventory for each tool. Record the credential source, principal, allowed actions, resource scope, expiration or rotation behavior, and whether the model can ever see the secret. Then test the negative path: a tool should deny an out-of-scope request even if the agent asks for it, and it should fail closed if credential retrieval fails. Prompt-level instructions are not a substitute for IAM or service-side authorization.
Security test matrix
| Test | Safe test setup | Expected result |
|---|---|---|
| Session swap | Authenticate as test user A and submit user B's known test session handle. | The application rejects the request before invoking AgentCore; no session content is returned. |
| Forged session field | Change runtimeSessionId in a request body while keeping the same valid login. | The backend ignores or rejects the field and uses its ownership-checked server mapping. |
| Tenant reassignment | Remove a test user from a tenant, then try to resume a session created while they were a member. | Current membership and session policy are checked; stale access does not survive by default. |
| Guessed or replayed ID | Try a random ID and replay a captured test ID from a different account. | Both fail authorization, whether or not the identifier happens to exist. |
| Shared-instance file access | Run two test agents with different trust levels on one instance and probe a seeded file owned by the other. | Deployment policy prevents the untrusted agent from sharing that host, or the test exposes a design that must be changed. |
| Credential scope | Ask a test tool to read a resource outside its intended account or tenant using a harmless canary record. | The downstream service denies the request; the agent's prompt cannot widen the credential's policy. |
| Identity forgery | Supply another user's ID in body fields or custom headers without that user's valid credential. | The application derives identity from verified authentication and never trusts the supplied value. |
| Audit correlation | Invoke test sessions through each supported principal and inspect CloudTrail records. | Reviewers can correlate the authenticated principal, target session ID, request, and application user mapping. |
Use synthetic tenants, synthetic files, and credentials with no access to production data. A good test harness records the authenticated test principal, the request chosen by the application, whether AgentCore was invoked, the downstream decision, and the final response. Test at the public API boundary as well as in a unit test of the mapping function. A unit test cannot prove that a controller did not bypass the mapping on an alternate route.
Run a two-user session-swap test
Put two test users behind the same invoking role and keep the session map in a server-side store. The application should select the runtime session from the authenticated principal, then pass that value to the AWS SDK. If a legacy request still includes a session field, reject a mismatch before calling AgentCore:
def invoke_for_user(user_id, prompt, requested_session_id=None):
owned_session_id = session_store.get_for_user(user_id)
if owned_session_id is None:
raise PermissionError("No authorized session")
if requested_session_id is not None and requested_session_id != owned_session_id:
raise PermissionError("Session does not belong to this user")
return agentcore.invoke_agent_runtime(
agentRuntimeArn=AGENT_RUNTIME_ARN,
runtimeSessionId=owned_session_id,
payload=prompt.encode("utf-8"),
)
The session-isolation harness uses a fake runtime to verify two users receive distinct mapped session IDs and that Alice's attempt to select Bob's session is denied before any runtime invocation. Run it with python3 -m unittest -v. Then replace the fake session map with your database lookup and exercise the same attack through the real authenticated HTTP route.
Use CloudTrail to investigate a routing anomaly
AWS documents that Runtime Instances CloudTrail events can show the invoking principal and target session in the same InvokeAgentRuntime event. Retrieve a small sample and compare those fields; use CloudTrail Lake or a saved query for larger investigations. Treat the result as detective evidence, not as a control that blocks the request.
aws cloudtrail lookup-events \
--region "$AWS_REGION" \
--lookup-attributes AttributeKey=EventName,AttributeValue=InvokeAgentRuntime \
--max-results 50 \
--query 'Events[].CloudTrailEvent' \
--output json |
jq -r '.[] | fromjson | [.eventTime, .userIdentity.arn, (.requestParameters.runtimeSessionId // .requestParameters.sessionId // "missing")] | @tsv'
For each candidate, compare the AWS principal with your application's authenticated user-to-session mapping, then review the downstream resource and whether an effect occurred. Keep the raw event restricted because account, runtime, and session identifiers are operational data.
Run the checks in layers
Start with a diagram showing the path from browser or client to application authentication, session lookup, AgentCore invocation, tools, and downstream services. Mark each point that selects an identity or credential. The most useful first test is usually session swap because it quickly proves whether the application is treating a session selector as an authorization decision.
Next, trace the data path. Create a test user, store a harmless marker in its session, and verify that a different user cannot recover it through conversation history, file search, tool output, or generated artifacts. Repeat after logout, tenant removal, session stop and resume, and session deletion. The goal is to test every supported lifecycle transition, not just the first invocation.
Finally, test the runtime's shared-instance assumptions and downstream credentials. AWS notes that CloudTrail can record the invoking principal and target session ID together for Runtime Instances. Use that evidence to alert on unexpected cross-principal routing. CloudTrail is detective evidence; it does not prevent a bad session mapping at request time.
What to put in the finding
For each failure, record the user identity, invoker principal, runtime ID, session ID, capacity provider, tool name, and resource touched. Store IDs in access-controlled evidence, not in a public report. Explain whether the issue came from the application mapping, an IAM policy, shared instance placement, or a downstream service. State whether the same condition can affect another tenant and whether a real side effect was possible.
Do not report a cross-user vulnerability solely because two users invoke the same runtime resource. The relevant evidence is that user A can cause the application to select user B's state or cause a downstream operation under B's authority. Conversely, a clean prompt-injection test does not prove session isolation. These are separate controls and deserve separate test results.
Acceptance criterion: the authenticated user determines the session and data scope; changing client-controlled identifiers cannot cross that boundary; each downstream tool enforces its own least-privilege policy; and an investigator can reconstruct the principal-to-session path from logs.
FAQ
- Does AgentCore Runtime bind runtimeSessionId to the caller?
- For Runtime Instances, AWS documents that the service validates the format of runtimeSessionId but does not verify that it belongs to the calling identity. A shared-principal backend must enforce session-to-user binding itself.
- Are containers a security boundary between agents on one Runtime Instance?
- AWS says agents that share an instance also share its filesystem, and that containers or separate processes on that same instance do not isolate the workloads from one another. Use separate trusted placements for agents that are not mutually trusted.
- Is a random session ID enough to stop cross-user access?
- No. Unpredictability can reduce guessing, but authorization must still verify that the authenticated user owns or may access the session. Treat the ID as a selector, not a credential.
Related reading
- NIST AI agent security controls for pentesting: broader tests for agent identity, tool boundaries, memory, and incident response.
- MCP agent identity and delegation security tests: a related way to verify which delegated identity may reach a tool.
- Bedrock Guardrails prompt attack filter: the separate content-screening layer and its documented gaps.
- How the Austa target harness captures tool intent safely: a test harness pattern that records intent without triggering real side effects.
AWS documents the Runtime Instances session model, shared-principal risk, and mitigations in its AWS security model and permissions guide for Runtime Instances.