> [!WARNING]
>
> **Preview
> --- Cloud Run sandboxes**
>
>
> This feature is
>
> subject to the "Pre-GA Offerings Terms" in the General Service Terms section of the
> [Service Specific
> Terms](https://docs.cloud.google.com/terms/service-terms#1).
>
> Pre-GA features are available "as is" and might have limited support.
>
> For more information, see the
> [launch stage descriptions](https://cloud.google.com/products/#product-launch-stages).

Cloud Run sandboxes let you execute untrusted code in an isolated
environment directly within container workloads. This capability helps AI agents
safely run sub-agents, execute computational tasks, or launch automated browsers
without risking the host system.

## Key advantages

Cloud Run sandboxes provide the following key advantages:

- **Fast creation**: Sandboxes are interactive and ready to execute commands
  almost instantly. By creating sandboxes within an existing
  Cloud Run resource where your agent runs, you reduce creation times
  when compared to creating a new Cloud Run resource for every task.
  This efficiency helps ensure that your agent remains responsive.

- **Security**: Sandboxes isolate process execution. By default, sandboxes
  don't have access to the parent workload, environment variables, secrets, or
  the Google Cloud metadata server. All sandboxes are completely isolated from
  each other.

- **Access control and environment** : Processes run with `sudo` privileges as
  a non-root user, letting you install tools using package managers such
  as `apt`, `pip`, or `npm` during execution. While the sandbox environment is
  ephemeral and deleted upon completion, you can use [persistent
  directories](https://docs.cloud.google.com/run/docs/code-execution#persist) or [snapshots](https://docs.cloud.google.com/run/docs/code-execution.md.txt#snapshots) to save specific
  workspaces or map data to a Cloud Storage bucket.

## Before you begin

1. [Install and initialize](https://docs.cloud.google.com/sdk/docs.md.txt) the gcloud CLI.
2. Deploy a Cloud Run resource, such as a [second generation](https://docs.cloud.google.com/run/docs/configuring/execution-environments.md.txt) [service](https://docs.cloud.google.com/run/docs/deploying.md.txt), [job](https://docs.cloud.google.com/run/docs/create-jobs.md.txt), [worker pool](https://docs.cloud.google.com/run/docs/deploy-worker-pools.md.txt), or [instance](https://docs.cloud.google.com/run/docs/instances/create-and-manage-instances.md.txt).

## Enable sandboxes

To use sandboxes, you must first enable them on your Cloud Run resource using the `--sandbox-launcher` flag or `sandboxLauncher` YAML attribute. For detailed configuration steps, choose from the following resource type:

- [Services](https://docs.cloud.google.com/run/docs/configuring/services/sandboxes.md.txt)
- [Jobs](https://docs.cloud.google.com/run/docs/configuring/jobs/sandboxes.md.txt)
- [Worker pools](https://docs.cloud.google.com/run/docs/configuring/workerpools/sandboxes.md.txt)
- [Instances](https://docs.cloud.google.com/run/docs/configuring/instances/sandboxes.md.txt) (Preview)

## Launch sandboxes

Once you enable sandboxes, you can launch sandboxes from within your container execution environment. The sandbox binary is located at `/usr/local/gcp/bin/sandbox`.

The examples in this guide use the `sandbox` command instead of its absolute path `/usr/local/gcp/bin/sandbox`.

You can execute the binary by referencing its absolute path in your source code. For example, to print `Hello` inside your isolated sandbox, choose one of the following options:

### Node.js

To execute the sandbox command from a Node.js application, include the following code:

```javascript
exec(`sandbox do -- /bin/echo "Hello"`, (e, stdout, stderr) => {
    res.send({ stdout, stderr });
});
```

### Python

To execute the sandbox command from a Python application, include the following code:

```python
import subprocess
result = subprocess.run(
    ["sandbox", "do", "--", "/bin/echo", "Hello"],
    capture_output=True,
    text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}
```

### Go

To execute the sandbox command from a Go application, include the following code:

```go
cmd := exec.Command("sandbox", "do", "--", "/bin/echo", "Hello")
out, err := cmd.CombinedOutput()
```

### Sandbox CLI

To execute the sandbox command directly from the command line, run the following command:

```bash
sandbox do -- /bin/echo "Hello"
```

To see the [complete list of available commands](https://docs.cloud.google.com/run/docs/reference/sandbox-cli.md.txt), run the `sandbox -h` command.

## Security boundaries for untrusted code

When you run untrusted or generated code inside a sandbox, don't relax isolation
flags to work around permission or network errors. Review the following security
boundaries before configuring sandbox flags:

- **Network egress (`--allow-egress`)** : Outbound network access is blocked by default. Enabling `--allow-egress` lets sandboxed code connect to external hosts and internal VPC endpoints that your Cloud Run resource can reach.
- **Bind mounts (`--mount`)** : Bind mounts attach host directories as read-write by default. Always append `,readonly` when exposing host directories to untrusted code, and never mount paths that contain secrets or credentials.
- **Root file system (`--rootfs` and `--write`)** : By default, `--rootfs` mounts the host container's file system as read-only at `/`. Don't store sensitive files on the host container's disk where sandboxed processes can read them.
- **Archive snapshots (`--import-tar`, `--export-tar`, `--sync-tar`, and
  `sandbox tar`)** : Never share writable `tar` archives across different untrusted users or tenants. Don't extract untrusted sandbox archives with `tar -xf` directly on the host container, because archives can contain malicious symlinks. Instead, list archive entries with `tar -tf` or re-import the archive into another sandbox using `--import-tar`.
- **Environment variables (`-e` and `--env`)** : Sandboxes don't inherit host environment variables by default. Never pass API keys, service account tokens, or secrets to untrusted code using `--env`.

## Use the sandbox command line capabilities

The `sandbox` command line tool contains commands to run, configure, and manage
sandboxes.

### Run a command in your sandbox

You can execute an instruction in a new, ephemeral sandbox using the `sandbox do`
command. The `sandbox do` command performs the following tasks:

1. Spins up a sandbox environment (`sandbox run`).
2. Executes the command you specify (`sandbox exec`).
3. Deletes the sandbox after successful execution (`sandbox delete`).

For example, to perform a math calculation inside the sandbox, run the
following code snippets for your preferred language. Ensure that any command
or tool you run, such as `python3`, is installed in your container image:

### Node.js

To execute the sandbox command from a Node.js application:

```javascript
exec(`sandbox do -- /usr/bin/python3 -c "print(1+2)"`, (e, stdout, stderr) => {
    res.send({ stdout, stderr });
});
```

### Python

To execute the sandbox command from a Python application:

```python
import subprocess
result = subprocess.run(
    ["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
    capture_output=True,
    text=True,
)
return {"stdout": result.stdout, "stderr": result.stderr}
```

### Go

To execute the sandbox command from a Go application:

```go
cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
out, err := cmd.CombinedOutput()
```

### Sandbox CLI

To execute the sandbox command directly from the command line:

```bash
sandbox do -- /usr/bin/python3 -c "print(1+2)"
```

If you run a command by name without its absolute path, such as `python3` instead of `/usr/bin/python3`, explicitly configure the `PATH` environment variable in the sandbox using the [`--env`](https://docs.cloud.google.com/run/docs/code-execution.md.txt#environment-variables) flag.

### Persist data across different executions

Sandboxes are ephemeral by default. To persist data across different sandbox
executions within the same Cloud Run instance, you can import and export
workspace file system state using standard `tar` archive files. Alternatively,
you can configure [bind mounts](https://docs.cloud.google.com/run/docs/code-execution.md.txt#bind-mounts) to share directories directly
between the host container and the sandbox environments.

Use the following flags when running the `sandbox do` command:

- `--export-tar`: Captures modified overlay files into a `tar` archive file upon completion.
- `--import-tar`: Extracts files from a `tar` archive file into the sandbox before execution.
- `--sync-tar`: Performs a two-way sync by importing before execution and exporting upon completion.

The `/tmp` directory inside the sandbox isn't part of the root file system
overlay, so archive files don't include files written to `/tmp`. To persist
data, write it to a different directory, such as `/workspace`.

For example, to pass data between two sandbox calls using archive files, run the following commands:

1. Write data inside a sandbox and export the state to an archive file:

   ```bash
   sandbox do --write --export-tar=/tmp/work.tar \
     -- /usr/bin/bash -c "mkdir -p /workspace && echo 'task-complete' > /workspace/status.txt"
   ```
2. Import the archive file in a subsequent call to retrieve the data:

   ```bash
   sandbox do --write --import-tar=/tmp/work.tar \
     -- /usr/bin/bash -c "cat /workspace/status.txt"
   ```

Alternatively, to automatically import existing archive state and export new changes in a single command, use `--sync-tar=/tmp/work.tar`.
When a sandbox process terminates, Cloud Run permanently deletes
ephemeral overlay files that weren't exported to an archive file.

### Run a command in the background

To run long-running processes, headless browsers, or background servers, such as
a background agent loop that continuously listens for incoming requests, use the
`--detach` flag.

For example, run the following command to start a detached sandbox with an idle
or background program:

```bash
sandbox run my-web-server --detach -- /usr/bin/long_running_or_idle_program
```

You can use the `detach` flag to reuse the same sandbox for multiple tests. To
interact with or run additional commands inside a running detached sandbox, use
the `sandbox exec` command and target your sandbox by its name.

For example, to execute a test command inside your existing `my-web-server`
background sandbox, run the following command:

```bash
sandbox exec my-web-server -- /usr/bin/python3 -c "print('test-complete')"
```

### Configure environment variables

Configure [environment
variables](https://docs.cloud.google.com/run/docs/configuring/services/environment-variables) on sandboxes
just like you would any other container. Sandboxes don't inherit environment
variables from the host container. You must explicitly provide them using
the `--env` flag when running the `sandbox` command.

For example, to pass a configuration variable into a sandbox, run the following command:

```bash
sandbox do --env AGENT_MODE="test" -- /usr/bin/bash -c "echo \$AGENT_MODE"
```

Avoid passing secrets using the `env` flag as they might be visible to the
sandbox processes.

### Create file system snapshots

Deploy a named sandbox in the background to handle continuous tasks like web
servers or long-running agent workflows, execute commands against the sandbox
dynamically, and capture its modified file system state into a `tar` archive file.

> [!TIP]
> **Tip:** If you run many commands repeatedly on a single sandbox, consider launching a sandbox once, with an idle entrypoint, such as `sleep 12m`, and then running the `sandbox exec` command that targets this sandbox for very fast command execution.

For example, to deploy a background sandbox, write a file to its overlay, and
snapshot its state to verify the data was captured, run the following commands:

1. Deploy a named sandbox in the background with write access enabled, creating
   a file within its workspace. Write the file to a path outside `/tmp`,
   because files written to `/tmp` inside the sandbox aren't captured in
   snapshots:

   ```bash
   sandbox run --write my-sandbox --detach -- /usr/bin/bash -c "echo 'hi' > /workspace/hello.txt && sleep 1h"
   ```
2. Create a snapshot of the running sandbox's modified file system
   using the `sandbox tar` command:

   ```bash
   sandbox tar my-sandbox --file=/tmp/foo.tar
   ```
3. List the contents of the snapshot archive file to verify that it contains
   the data written inside the sandbox:

   ```bash
   tar -tf /tmp/foo.tar
   ```

   You should see the following results:

   ```bash
   ./
   ./workspace/
   ./workspace/hello.txt
   ```

   > [!CAUTION]
   > **Caution:** Don't extract untrusted sandbox archives with `tar -xf` directly on the host container. Instead, inspect archive entries with `tar -tf` or re-import the archive into a sandbox using `--import-tar`.

### Configure networking

By default, all outbound traffic from the sandbox is blocked. To allow outbound network access, use the `--allow-egress` flag:

For example, to fetch data from an external endpoint, run the following command:

```bash
sandbox do --allow-egress -- /usr/bin/python3 -c 'import urllib.request; print(urllib.request.urlopen("https://google.com").getcode())'
```

This command returns the standard HTTP status code `200`, indicating a successful
connection.

### Access the file system

By default, processes you execute inside the sandbox have read-only access to the host container root file system. You can use the `--write` flag to enable writing to a temporary file system (tmpfs) overlay. However, the writes will be lost when the sandbox is deleted. To enable persistent writing to the host container, you can configure [bind mounts](https://docs.cloud.google.com/run/docs/code-execution.md.txt#bind-mounts).

The `/tmp` directory inside the sandbox is always writable, even without the
`--write` flag. The `/tmp` directory is deleted when the sandbox is deleted, and
it isn't included in [snapshots](https://docs.cloud.google.com/run/docs/code-execution.md.txt#snapshots) or [archive files](https://docs.cloud.google.com/run/docs/code-execution.md.txt#persist).

#### Default read-only access

Inside the sandbox, processes can read files from the host container,
and they can't write to the root file system outside of `/tmp`.

The following examples assume you are executing commands from the root directory
(`/`) of your host container.

To verify default read-only access, run the following commands:

1. Create a Python script on the host container:

   ```bash
   mkdir -p /tmp/my-scripts
   echo "print('hi')" > /tmp/my-scripts/task.py
   ```
2. Verify the file exists locally:

   ```bash
   cat /tmp/my-scripts/task.py
   ```
3. Execute the file inside your sandbox:

   ```bash
   sandbox do -- /usr/bin/python3 /tmp/my-scripts/task.py
   ```

   This command returns `hi`, confirming that the sandbox has read access.

   If you attempt to write data directly to the sandbox root file system without
   additional configuration, the execution fails. For example, attempting to write
   to the root directory (`/`) inside the default sandbox returns a read-only file
   system error:

   Run the following command to write to the root file system:

   ```bash
   sandbox do -- /usr/bin/bash -c "echo 'hi' > /testfile.txt"
   ```

   The command fails with the following error:

   ```bash
   /usr/bin/bash: line 1: /testfile.txt: Read-only file system
   Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1
   ```

#### Share data using bind mounts

By default, the `--mount` flag attaches host directories as read-write. When you
expose host directories to untrusted code, [configure read-only
mounts](https://docs.cloud.google.com/run/docs/code-execution#configure-read-only-mounts) by appending `,readonly`.

To allow processes inside the sandbox to write persistable data to a dedicated
directory, attach a shared volume using the `--mount` flag:

1. Create a shared volume directory on the host container and seed it with an
   initial file:

   ```bash
   mkdir -p /tmp/my-volume
   echo 'read' > /tmp/my-volume/readwrite.txt
   ```
2. Execute the sandbox to read the file from the bind mount path:

   ```bash
   sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "cat /mnt/my-mount/readwrite.txt"
   ```

   This command returns `read`.
3. Execute the sandbox to write new data back to the host from inside the mount:

   ```bash
   sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount -- /usr/bin/bash -c "echo 'write' > /mnt/my-mount/readwrite.txt"
   ```
4. Verify on the host container that the sandbox successfully modified the
   file:

   ```bash
   cat /tmp/my-volume/readwrite.txt
   ```

   This command returns `write`.

#### Configure read-only mounts

To grant the sandbox access to a host directory while explicitly preventing it
from modifying files, append the `readonly` attribute to the mount
specification.

For example, run the following command to test write restrictions on a
read-only bind mount:

```bash
sandbox do --mount type=bind,source=/tmp/my-volume,destination=/mnt/my-mount,readonly -- /usr/bin/bash -c "echo 'fails' > /mnt/my-mount/hello.txt"
```

The write attempt fails with the following error:

```bash
/usr/bin/bash: line 1: /mnt/my-mount/hello.txt: Read-only file system
Error: failed to exec in container: cmd.Wait(exec) failed: exit status 1
```

### View logs

Cloud Run automatically captures sandbox lifecycle events, such as execution starts and exits, in Cloud Logging.

The `sandbox` CLI writes standard output (`stdout`) and standard error (`stderr`) from sandboxed commands directly to the standard streams of the invoking process. To view these logs in Cloud Logging, route the streams to your container's standard output and standard error:

### Node.js

```javascript
const { exec } = require('child_process');
const child = exec('sandbox do -- /usr/bin/python3 -c "print(1+2)"');
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
```

### Python

```python
subprocess.run(
    ["sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)"],
    stdout=sys.stdout,
    stderr=sys.stderr,
)
```

### Go

```go
cmd := exec.Command("sandbox", "do", "--", "/usr/bin/python3", "-c", "print(1+2)")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
```

## What's next

- Learn more about [hosting AI agents on Cloud Run](https://docs.cloud.google.com/run/docs/ai-agents.md.txt).
- Explore [browser and OS automation in Cloud Run](https://docs.cloud.google.com/run/docs/browser-automation.md.txt).
- Review the [container runtime contract](https://docs.cloud.google.com/run/docs/container-contract.md.txt).