Skip to content

fix(code_executors): harden ContainerCodeExecutor sandbox by default#6074

Open
adilburaksen wants to merge 1 commit into
google:mainfrom
adilburaksen:harden/container-code-executor-network
Open

fix(code_executors): harden ContainerCodeExecutor sandbox by default#6074
adilburaksen wants to merge 1 commit into
google:mainfrom
adilburaksen:harden/container-code-executor-network

Conversation

@adilburaksen

Copy link
Copy Markdown

Summary

ContainerCodeExecutor runs model-generated code, which can be influenced by untrusted input (e.g. via prompt injection). It starts the container with default Docker networking and no capability restrictions, so the executed code can reach the cloud metadata endpoint (169.254.169.254) — which yields the host service-account token — reach internal services, or escalate privileges.

This is inconsistent with the isolation posture of every other ADK code executor:

  • GkeCodeExecutor runs under gVisor with cap_drop: ["ALL"], non-root, read-only root filesystem, and a strict security context.
  • BuiltInCodeExecutor / VertexAiCodeExecutor / AgentEngineSandboxCodeExecutor run in managed server-side sandboxes.
  • UnsafeLocalCodeExecutor is explicitly documented as unsafe.

ContainerCodeExecutor was the only executor running code with full network access and no isolation flags or warning.

Change

  • Start the container with network_disabled=True by default. This is exposed as a configurable network_disabled field — set it to False to re-enable networking when the executed code is trusted.
  • Drop all Linux capabilities (cap_drop=["ALL"]) and forbid privilege escalation (security_opt=["no-new-privileges"]), matching GkeCodeExecutor.
  • Document the security posture in the class docstring and point users to the sandboxed executors for untrusted code.
  • Add unit tests covering the hardened defaults and the opt-in network path.

Compatibility

Code that legitimately needs network access can opt back in with ContainerCodeExecutor(..., network_disabled=False). Dropping capabilities and no-new-privileges do not affect normal Python code execution.

@adk-bot

adk-bot commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Response from ADK Triaging Agent

Hello @adilburaksen, thank you for creating this PR to harden the ContainerCodeExecutor sandbox!

While checking this PR against our contribution guidelines, I noticed a few things that need to be addressed:

  1. Testing Plan: Please include a dedicated testing plan section in your PR description explaining how you tested these changes.
  2. Logs / Test Results: Please provide logs or test output (e.g., the output of the new pytest unit tests) showing that the test suite passes successfully.
  3. CI Header Check Failure: The header-check CI status check failed. Please ensure all new and modified files have the correct Apache 2.0 license headers. You can automatically verify and fix this by running pre-commit run --all-files locally before pushing.

These steps will help the maintainers review your contribution more quickly and efficiently. Thank you!

@rohityan rohityan self-assigned this Jun 11, 2026
@rohityan rohityan added the request clarification [Status] The maintainer need clarification or more information from the author label Jun 11, 2026
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @adilburaksen, Thank you for your contribution! We appreciate you taking the time to submit this pull request. Can you please fix the failing unit tests before we can proceed with the review.

@rohityan rohityan added the tools [Component] This issue is related to tools label Jun 11, 2026
ContainerCodeExecutor runs model-generated code, which may be influenced
by untrusted input (e.g. prompt injection). Start the container with
networking disabled, all Linux capabilities dropped, and no-new-privileges
by default so executed code cannot reach the network (including the cloud
metadata endpoint at 169.254.169.254), internal services, or exfiltration
destinations, nor escalate privileges. Networking can be re-enabled via
network_disabled=False when the executed code is trusted.

Add unit tests covering the hardened defaults and the opt-out, and add
docker to the test dependency group so the tests are importable in CI.
@adilburaksen adilburaksen force-pushed the harden/container-code-executor-network branch from f40320e to f7eaec2 Compare June 12, 2026 06:39
@adilburaksen

Copy link
Copy Markdown
Author

@rohityan fixed and rebased onto latest main. Summary of this push:

Root cause of the failing tests: the new test module imports ContainerCodeExecutor, whose module does a top-level import docker. docker was only in the extensions optional group, not the test group, so it wasn't installed in the unit-test env and collection failed with ModuleNotFoundError: No module named 'docker'.

Changes:

  • Added docker>=7 to the test dependency group (mirrors how kubernetes is provided for the GKE executor tests) so the module is importable in CI.
  • Fixed the license-header year on the new test file (2025 → 2026), which clears header-check.
  • Rebased onto current main, so the branch is no longer BEHIND.

Testing plan / results — ran the new tests locally with docker installed:

$ pytest tests/unittests/code_executors/test_container_code_executor.py -q
2 passed in 3.50s

The two tests assert that, by default, containers.run is called with network_disabled=True, cap_drop=['ALL'], and security_opt=['no-new-privileges'], and that network_disabled=False is honored when explicitly set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

request clarification [Status] The maintainer need clarification or more information from the author tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants