CVE-2026-16584: Verified Reproduction
CVE-2026-16584: AWS API MCP Server security policy bypass via startup initialization failure
CVE-2026-16584 is verified against awslabs.aws-api-mcp-server · pip. Affected versions: >=0.2.13 and <1.3.47; equivalently 0.2.13 through 1.3.46. Fixed in 1.3.47, released on PyPI on 2026-07-22. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00303.
What Is CVE-2026-16584?
CVE-2026-16584 is a high-severity vulnerability affecting awslabs.aws-api-mcp-server >=0.2.13 and <1.3.47; equivalently 0.2.13 through 1.3.46.. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00303).
CVE-2026-16584 Severity
CVE-2026-16584 is rated high severity.
High — serious impact or readily exploitable. Prioritize remediation.
Affected awslabs.aws-api-mcp-server Versions
awslabs.aws-api-mcp-server · pip versions >=0.2.13 and <1.3.47; equivalently 0.2.13 through 1.3.46. are affected.
How to Reproduce CVE-2026-16584
pruva-verify REPRO-2026-00303 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00303/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-16584
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
MCP call_aws request for deny-listed aws sts get-caller-identity command after forced startup index failure
- python -m awslabs.aws_api_mcp_server.server stdio startup
- get_read_only_operations failure
- MCP call_aws
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-16584
CVE-2026-16584 is a fail-open initialization bug in awslabs.aws-api-mcp-server. Versions before the fix load the read-operations index at server startup for later per-request security-policy decisions. If that startup load fails, the vulnerable server catches the exception, sets READ_OPERATIONS_INDEX = None, and continues serving MCP requests. Later call_aws requests skip the configured deny/elicitation policy path when the index is absent, allowing an AWS operation that a local security policy was configured to deny to reach the AWS call boundary.
- Package/component affected:
awslabs.aws-api-mcp-serverin theawslabs/mcprepository, specificallysrc/aws-api-mcp-server/awslabs/aws_api_mcp_server/server.pyand the security-policy path usingcore/metadata/read_only_operations_list.pyandcore/security/policy.py. - Affected versions: Submitted claim states
>=0.2.13and<1.3.47. This run anchored the vulnerable build to fixed commitab1bbebc097d674c1cdd4bd75a8f313be18473bf^(70d8c4cb82601a0e48328e34bf7a81b5a6fba073) and the fixed negative control toab1bbebc097d674c1cdd4bd75a8f313be18473bf. - Risk level and consequences: High. A local actor or MCP client using a server configured with a security policy can cause denied or gated AWS CLI operations to be executed by the server process after the read-operations index fails to initialize. IAM permissions still bound what AWS accepts, but the server-level denyList/elicitList control is bypassed for the process lifetime.
Impact Parity
- Disclosed/claimed maximum impact: Authorization/policy bypass for configured denyList or elicitList entries, allowing denied/gated AWS CLI operations to reach the AWS-call boundary after startup initialization failure.
- Reproduced impact from this run: Full authorization bypass at the claimed CLI/MCP server boundary. The vulnerable server started via the real
awslabs.aws_api_mcp_server.serverstdio entrypoint, logged read-operations index initialization failure, accepted an MCPcall_awsrequest for a command present indenyList, and performed an HTTP POST to a local fake STS endpoint. The fixed commit failed closed during startup and never reached the fake AWS endpoint. - Parity:
full - Not demonstrated: No real AWS account mutation was attempted. The proof uses a local fake AWS HTTP endpoint as the downstream AWS-call boundary to avoid external side effects; the boundary request body and botocore-signed headers demonstrate that the real server execution path reached the AWS client call.
Root Cause
The root cause is fail-open handling of a required security-policy dependency. In vulnerable commit 70d8c4cb82601a0e48328e34bf7a81b5a6fba073, main() always tries to load READ_OPERATIONS_INDEX = get_read_only_operations(), but catches any exception, logs Failed to load read operations index, sets READ_OPERATIONS_INDEX = None, and continues to server.run(...). Later, call_aws_helper() only invokes check_security_policy(ir, READ_OPERATIONS_INDEX, ctx) when READ_OPERATIONS_INDEX is not None. With the index set to None, a normal denyList check is skipped unless the separate read-only or mutation-consent modes are enabled.
The fix commit is ab1bbebc097d674c1cdd4bd75a8f313be18473bf (fix(aws-api-mcp-server): Security Policy Bypass via Startup Initialization Failure). It removes the fail-open fallback and changes request-time behavior so an absent READ_OPERATIONS_INDEX is treated as a hard denial: Execution of this operation is denied because the security policy enforcement data failed to initialize. In the startup path, initialization failure is re-raised, so the stdio MCP server does not finish initialization.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.sh. - The script:
- Uses
bundle/project_cache_context.jsonwhen present and checks out/reuses/pruva/project-cache/repo. - Resolves vulnerable commit
ab1bbebc097d674c1cdd4bd75a8f313be18473bf^and fixed commitab1bbebc097d674c1cdd4bd75a8f313be18473bf. - Creates isolated source trees for each commit and installs the real package in a Python virtual environment.
- Starts the real server via
python -m awslabs.aws_api_mcp_server.serverover MCP stdio. - Writes a real
~/.aws/aws-api-mcp/mcp-security-policy.jsonwithdenyList: ["aws sts get-caller-identity"]. - Forces read-operations index initialization failure with an invalid proxy for
servicereference.us-east-1.amazonaws.comwhile preserving localhost access. - Sends an MCP
call_awstool request foraws sts get-caller-identity --endpoint-url http://127.0.0.1:<fake-sts-port>. - Runs two vulnerable attempts and two fixed negative-control attempts.
- Uses
- Expected evidence:
- Vulnerable attempts show
mcp_initialized=true,startup_failure_observed=true,fake_aws_boundary_reached=true, andpolicy_denial_observed=false. - Fixed attempts show startup failure,
mcp_initialized=false, andfake_aws_boundary_reached=false.
- Vulnerable attempts show
Evidence
bundle/logs/reproduction_steps.logcontains the full script output, resolved commit IDs, patch-presence excerpts, and per-attempt summaries.bundle/logs/repro/summary.jsoncontains structured results. In the latest run it recorded:vulnerable_all_bypassed: truefixed_all_fail_closed: true
bundle/logs/repro/vulnerable_attempt_1.jsonandbundle/logs/repro/vulnerable_attempt_2.jsonshow both vulnerable attempts reached the fake AWS boundary. Each includes a captured POST with bodyAction=GetCallerIdentity&Version=2011-06-15, botocoreAuthorizationheaders, and a successful MCP tool response forAWS Security Token Service / GetCallerIdentity.bundle/logs/repro/vulnerable_attempt_1_server.logandbundle/logs/repro/vulnerable_attempt_2_server.logshow the server loggedFailed to load read operations index, then continued to start FastMCP over stdio and handledcall_tool call_aws.bundle/logs/repro/fixed_attempt_1.jsonandbundle/logs/repro/fixed_attempt_2.jsonshow no fake AWS calls.bundle/logs/repro/fixed_attempt_1_server.logandbundle/logs/repro/fixed_attempt_2_server.logshow the fixed server raisedRuntimeError: Error retrieving the service reference document...during startup and closed the MCP connection.bundle/repro/runtime_manifest.jsonrecords the runtime-backed entrypoint ascli_command, with target path reached and proof artifacts listed.
Recommendations / Next Steps
- Upgrade
awslabs.aws-api-mcp-serverto version1.3.47or later, containing fix commitab1bbebc097d674c1cdd4bd75a8f313be18473bf. - Keep the security-policy fail-closed invariant: if read-operations metadata cannot be loaded, do not serve requests and do not execute AWS CLI operations.
- Add regression tests that force
get_read_only_operations()to fail and assert both startup refusal and request-time denial for absent policy-enforcement data. - Ensure operational monitoring alerts on
Failed to load read operations indexor equivalent startup failures.
Additional Notes
- The reproduction script was run successfully twice consecutively after fixing an initial brittle grep preflight.
- The proof is idempotent: it creates temporary HOME directories, local fake AWS endpoints, and isolated source archives on each run.
- The fake AWS endpoint is intentionally local and side-effect free. It proves the downstream AWS-call boundary is reached without using real cloud credentials or changing AWS resources.
CVE-2026-16584 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-16584
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-16584
Upgrade awslabs.aws-api-mcp-server · pip to 1.3.47, released on PyPI on 2026-07-22. or later.
FAQ: CVE-2026-16584
Is CVE-2026-16584 exploitable?
How severe is CVE-2026-16584?
What type of vulnerability is CVE-2026-16584?
Which versions of awslabs.aws-api-mcp-server are affected by CVE-2026-16584?
Is there a fix for CVE-2026-16584?
How can I reproduce CVE-2026-16584?
Is the CVE-2026-16584 reproduction verified?
References for CVE-2026-16584
Authoritative sources for CVE-2026-16584 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.