Skip to content
Runtime

How to mount an S3 bucket in a sandbox

Store the bucket's key as a Runtime secret. Then call sbx.mounts.add({ provider: "s3", bucket, path, secret }).

On Runtime, the bucket's key stays outside the sandbox. You store the key once, as a secret. The mount client inside the sandbox signs its requests with a placeholder. Runtime's egress proxy signs each request again with the real key, as it leaves for the bucket's endpoint. So code in the sandbox, or a prompt injection that steers it, has nothing worth stealing. Amazon S3, Cloudflare R2, Google Cloud Storage and any S3-compatible store work. A public bucket needs no key at all (mount your own bucket).

Store the key and mount the bucket

Terminalprintf %s "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" | runtime secrets set DATA_BUCKET \  --host s3.eu-west-1.amazonaws.com --header Authorization --format 'AWS4-HMAC-SHA256 {value}'runtime sandboxes mount "${id}" s3://my-data/datasets /data --secret DATA_BUCKET --region eu-west-1runtime sandboxes mounts "${id}"runtime sandboxes unmount "${id}" /data
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.secrets.set("DATA_BUCKET", {  value: `${process.env.AWS_ACCESS_KEY_ID}:${process.env.AWS_SECRET_ACCESS_KEY}`,  hosts: ["s3.eu-west-1.amazonaws.com"],  header: "Authorization",  format: "AWS4-HMAC-SHA256 {value}",});await using sbx = await runtime.sandboxes.create();await sbx.mounts.add({  provider: "s3",  bucket: "my-data",  prefix: "datasets",  region: "eu-west-1",  path: "/data",  secret: "DATA_BUCKET",});console.log((await sbx.exec("ls -la /data")).stdout);await sbx.exec("echo 'a,b' > /data/result.csv", { check: true }); // reaches the bucket on close
Pythonimport osfrom withruntime import Runtimeruntime = Runtime()runtime.secrets.set(    "DATA_BUCKET",    value=f"{os.environ['AWS_ACCESS_KEY_ID']}:{os.environ['AWS_SECRET_ACCESS_KEY']}",    hosts=["s3.eu-west-1.amazonaws.com"],    header="Authorization",    format="AWS4-HMAC-SHA256 {value}",)with runtime.sandboxes.create() as sbx:    sbx.mounts.add(provider="s3", bucket="my-data", prefix="datasets", region="eu-west-1",                   path="/data", secret="DATA_BUCKET")    print(sbx.exec("ls -la /data").stdout)

The secret must match exactly. Its value is ACCESS_KEY_ID:SECRET_ACCESS_KEY, with :SESSION_TOKEN added for temporary keys. Its header is Authorization. Its format is AWS4-HMAC-SHA256 {value}. Its host is the bucket's endpoint.

R2, Google Cloud Storage and other stores

Provider Mount with The secret's host
Amazon S3 provider: "s3", region (us-east-1 when omitted) s3.<region>.amazonaws.com
Cloudflare R2 provider: "r2", accountId <account id>.r2.cloudflarestorage.com
Google Cloud Storage provider: "gcs", with an HMAC key storage.googleapis.com
Any S3-compatible provider: "s3", endpoint Your store's own host
A public bucket Any of the above, no secret None
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();await sbx.mounts.add({  provider: "r2",  accountId: "<cloudflare account id>",  bucket: "models",  path: "/models",  secret: "R2_MODELS",  readOnly: true,});console.log(await sbx.mounts.list());

prefix mounts only the keys under it. readOnly refuses writes. That suits a shared dataset that jobs must not change.

How the mount behaves

Question Answer
What runs it rclone, installed in the sandbox the first time you mount. It adds a few seconds
When a write reaches the bucket When the file is closed
Two sandboxes, one bucket Both can mount it. A file that both write ends with the version closed last
Pause and wake The mount lasts through both
Stop and restart The mount ends at a stop. Mount it again after a restart
Network HTTPS to the endpoint, through the sandbox's own rules, like any other host
Where the key lives Sealed on Runtime's servers. No API, tool or command returns it

A mount, a volume or the AWS SDK?

  • A mount fits data that already lives in a bucket: datasets, model files, results other systems read.
  • A volume is a disk that outlives sandboxes. It sits on the sandbox's own server. Use it for data a program writes and rereads many times, such as a package cache or a database file.
  • The AWS SDK with an identity token fits code that calls S3's API itself, for listing, presigned URLs or other AWS services. It needs no key at all (use identity tokens with AWS).

Mistakes and how Runtime handles them

  • The secret's host does not match the endpoint. The proxy adds the real key only on HTTPS requests to the secret's hosts. For S3, that is the regional host, s3.<region>.amazonaws.com.
  • Pasting the key into an environment variable. Then the key lives in the sandbox. With the secret, a sandbox that prints its whole environment shows only a worthless placeholder.
  • Reading a file from elsewhere right after writing it. A write reaches the bucket when the file is closed. Close the file, or finish the program, first.
  • An allow list that leaves the bucket out. The bucket is reached through the sandbox's network rules. Allow its endpoint host when you narrow them (turn off sandbox internet).
  • An MCP agent. The same mounts are the runtime_sandboxes_mounts tool's mount, list and unmount actions.

Start

Terminalnpx withruntime sandboxes run --keep -- ls /workspace

A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card needed. Then mount a bucket into the sandbox it kept, with runtime sandboxes mount.

Facts on this page were checked on 26 October 2026.

Related.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card