Skip to content

ExecuteBashTool ignores resource limits that are set to 0 #7983

Closed

Description

@Fruiterer333

Describe the Bug:

BashToolPolicy says that max_memory_bytes, max_file_size_bytes and max_child_processes "will be enforced upon the spawned subprocess". A limit set to 0 is not enforced: _set_resource_limits (src/google/adk/tools/bash_tool.py) checks each one with if policy.max_file_size_bytes:, and 0 is falsy, so setrlimit is never called and the command runs with no limit at all.

So BashToolPolicy(max_file_size_bytes=0), meant to stop a command from writing to files, allows writes of any size, and max_child_processes=0 does not stop a command from starting child processes. A limit of 1 is enforced, which makes 0 the least restrictive value instead of the most restrictive.

Steps to Reproduce:

  1. Install google-adk from main (reproduced @ f8ced6f).
  2. Run the script under "Minimal Reproduction Code". It runs the same dd command, which writes 4096 bytes, once with max_file_size_bytes=1024 and once with max_file_size_bytes=0.

Expected Behavior:

With max_file_size_bytes=0, the write is blocked and the file stays empty, the way the write is cut off at 1024 bytes with max_file_size_bytes=1024.

Observed Behavior:

max_file_size_bytes=1024: returncode=-25, bytes written=1024
max_file_size_bytes=0: returncode=0, bytes written=4096

(-25 is SIGXFSZ, the signal sent when a process goes over its file size limit.)

Environment Details:

  • ADK Library Version (pip show google-adk): main @ f8ced6f
  • Desktop OS: macOS 26.6.2
  • Python Version (python -V): 3.12.7

Model Information:

  • Are you using LiteLLM: N/A (no model call needed to reproduce)
  • Which model is being used: N/A

Minimal Reproduction Code:

"""max_file_size_bytes=0 is ignored by ExecuteBashTool (google/adk-python)."""
import asyncio
import pathlib
import tempfile
from unittest import mock

from google.adk.tools.bash_tool import BashToolPolicy, ExecuteBashTool
from google.adk.tools.tool_context import ToolContext

# A command that writes 4096 bytes to a file in the workspace.
COMMAND = "dd if=/dev/zero of=out.bin bs=1024 count=4"


async def run(limit: int) -> None:
  with tempfile.TemporaryDirectory() as workspace:
    tool = ExecuteBashTool(
        workspace=pathlib.Path(workspace),
        policy=BashToolPolicy(max_file_size_bytes=limit),
    )
    ctx = mock.create_autospec(ToolContext, instance=True)
    ctx.tool_confirmation = mock.Mock(confirmed=True)
    result = await tool.run_async(args={"command": COMMAND}, tool_context=ctx)
    out = pathlib.Path(workspace, "out.bin")
    size = out.stat().st_size if out.exists() else None
    print(
        f"max_file_size_bytes={limit}: returncode={result.get('returncode')},"
        f" bytes written={size}"
    )


asyncio.run(run(1024))
asyncio.run(run(0))

Additional Context:

Checking is not None instead of truthiness fixes it, since None is the default that means "no limit". I'm happy to send a PR.

Activity

  1. added a commit that references this issue on Nov 5, 2026
    a702e3c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions