Skip to content

fix(agentcore): scope DynamoDB credentials to each execution - #526

Closed
jeromevdl wants to merge 2 commits into
mainfrom
fix/agentcore-ddb-execution-scope
Closed

jeromevdl wants to merge 2 commits into
mainfrom
fix/agentcore-ddb-execution-scope

Conversation

@jeromevdl

@jeromevdl jeromevdl commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

AgentCore accesses execution data through a shared runtime role, allowing code running in one invocation to address another execution's DynamoDB partition. This change exchanges a signed invocation grant through the credential broker for an STS session tagged with the execution ID. IAM restricts that session to EXEC#<executionId>. The new runtime role explicitly denies ambient access to the execution table and its indexes.

The scoped store is propagated through HTTP handlers, MCP, CLI processes and reviewer/persona subprocesses. Credentials are cached and refreshed without falling back to ambient credentials. Managed environment revisions record whether their base image supports scoped execution credentials; known legacy images retain the legacy role. Unresolved ancestry fails runtime creation, including when the ten-level lookup limit is reached.

The Terraform hardening test now recognizes the shared DynamoDB action list used by both runtime roles, so its KMS coverage assertion continues to check both roles.

Validation

  • CI passed on commit 4ab819fa: tests on Node.js 22 and 24, lint, Terraform validation and CodeQL. The focused Terraform hardening suite also passed all seven tests locally.
  • The original commit passed 1,843 tests across 65 impacted suites, plus formatting, lint, secret scanning and dependency graph checks.
  • 15 live broker/DynamoDB checks passed: own-partition reads and a condition-only transaction succeeded; cross-partition operations, mixed-partition transactions, scans and index queries were denied. Mismatched, tampered and expired grants were rejected.
  • A deployed workflow resumed after its reverse-engineering approval and completed code generation without a recorded runtime error.
  • A read-only probe inside the deployed AgentCore container confirmed the ambient and scoped STS identities. Ambient execution-table access was denied; scoped credentials allowed the intended partition and denied another. The credential-provider source hash matched the tested commit.
  • The container probe also verified refresh through the live broker, concurrent refresh deduplication, failure without credential fallback, recovery, warm process reuse and process recreation after a session stop. All 37 assertions and both process-lifecycle comparisons passed. Test sessions were stopped afterward; probes made no DynamoDB data changes.
  • Refresh testing advanced the provider's injected clock while using real AWS credentials and calls. It was not a wall-clock expiry soak test.

@jeromevdl
jeromevdl marked this pull request as ready for review October 8, 2026 17:21
@jeromevdl
jeromevdl marked this pull request as draft October 8, 2026 17:25
@jeromevdl
jeromevdl marked this pull request as ready for review October 8, 2026 18:46
@jeromevdl
jeromevdl marked this pull request as draft October 9, 2026 12:07

@JWThewes JWThewes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on 4ab819f for two P2s attached inline: the new execution grant can escape through CLI output, and the local E2E harness inherits the production MCP entrypoint instead of selecting its fixture. Both were reproduced deterministically on this head using synthetic/inert credentials; the grant reproduction used the real runStage and broker authorization code with a stubbed CLI process and mocked STS.

The review compared this head with main at 5aabcaa. Validation: 3,623 tests passed and 3 skipped across seven affected backend projects; lint, formatting, secret scanning, dependency/SDK checks, seven Terraform hardening tests, Terraform validation and five affected Lambda builds passed. Inspected Node 22/24 CI logs each report 4,584 passed and 3 skipped. No live AWS/model E2E, deployed workflow or wall-clock expiry soak was performed. The existing broker/store design can be retained; both findings call for focused corrections and regression coverage.

...mcpSecretEnv,
...invocation.env,
...driver.envForAuth(env),
...executionDataEnv(env),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Redact the execution grant before logging, persisting or broadcasting CLI output

This addition puts the new eight-hour V2_EXECUTION_DATA_GRANT bearer capability in the CLI/tool environment. A tool that prints its environment can return the grant as ordinary output. cli/spawn.js:155 copies raw stdout to the container log, and emitCliOutput below persists and broadcasts content and display without redaction. Keeping the grant out of generated MCP configuration does not protect these paths.

Reproduced with the existing run-stage fixtures, a locally signed synthetic grant for execution e1, and a stubbed OpenCode process returning its native bash-tool event for printenv V2_EXECUTION_DATA_GRANT:

  • The real runStage completed successfully.
  • The grant appeared in captured container stdout, appendOutput records and agent.output broadcasts.
  • Passing the captured value to the real authorizeExecutionDataRequest with mocked STS succeeded and requested the original execution_id=e1 session tag.

A caller who obtains this output and can invoke the broker, including code running in another AgentCore invocation, can therefore redeem the copied grant for the source execution's partition during its validity period. The general lack of output redaction predates this PR, but introducing this DynamoDB capability into that unprotected path is new.

Please redact the invocation grant before raw stdout/stderr logging and before normalized output persistence/broadcast, including display fields. Handle values split across stream chunks. Add a regression that emits the synthetic grant as a tool result and asserts it is absent from container output, stored output and broadcasts. This reproduction used no real secret, model call or AWS request.

const tableName = process.env.V2_PROCESS_TABLE || 'aidlc-local-e2e';
const workspaceDir = process.env.V2_WORKSPACE_DIR || '/mnt/workspace';
const mcpEntry = process.env.V2_MCP_ENTRY || '/opt/agentcore/mcp/index.js';
const mcpEntry = process.env.V2_MCP_ENTRY || '/opt/agentcore/test/fixtures/mcp-stdio-entry.js';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Override the production MCP entrypoint when launching the local E2E container

The fixture path here is only selected when V2_MCP_ENTRY is absent. The runtime image always sets V2_MCP_ENTRY=/opt/agentcore/mcp/index.js in lambda/agentcore/Dockerfile:149, and container_args() in scripts/agent-e2e-testing.sh:179 does not override it. Consequently, the supported local E2E still selects the production server instead of the new fixture.

That server now calls createExecutionStore and requires an execution grant, while this harness supplies inert DynamoDB credentials and no grant. A credential-free reproduction evaluated this exact expression with the Dockerfile environment, confirmed selection of /opt/agentcore/mcp/index.js, and invoked the production startup with the harness's relevant environment. It failed immediately with Execution data grant is required, before any network request.

The documented fresh/park/resume E2E therefore cannot complete its required MCP question, metric and output checks. The current stdio tests inject the fixture directly and do not cover the image's inherited default.

Please set the fixture entrypoint explicitly in the local E2E container arguments, or introduce an E2E-specific override that cannot be shadowed by the production default. Add a regression exercising entrypoint selection with the Dockerfile environment present, and verify that local MCP startup reaches the test store. The credentialed CLI lifecycle itself was not run during this review.

@jeromevdl

Copy link
Copy Markdown
Collaborator Author

Removing this one in favor of #613-#615

@jeromevdl jeromevdl closed this Oct 26, 2026
@jeromevdl jeromevdl added area/agents AgentCore runtime: CLI drivers, MCP tools, workspace and Git operations area/backend Lambda APIs, lambda/shared, v2-orchestrator area/infra Terraform, installer and deployment area/ci GitHub Actions, hooks, lint, release tooling, E2E harness size/L < 3000 changed lines (lockfiles excluded) fix Bug fix: PR title starts with fix: or fix(scope): labels Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agents AgentCore runtime: CLI drivers, MCP tools, workspace and Git operations area/backend Lambda APIs, lambda/shared, v2-orchestrator area/ci GitHub Actions, hooks, lint, release tooling, E2E harness area/infra Terraform, installer and deployment fix Bug fix: PR title starts with fix: or fix(scope): size/L < 3000 changed lines (lockfiles excluded)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants