Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
sandbox-runtime — Una herramienta de sandboxing ligera para aplicar restricciones de sistema de archivos y red en procesos arbitrarios a nivel del sistema operativo, sin necesidad de un contenedor. | Kitploit
Herramientas/GitHubGitHub/anthropic-experimental/sandbox-runtime
Herramientas DefensivasSeguridad de ContenedoresAnálisis Dinámico (Sandboxing)Auditoría de ConfiguraciónVirtualización de SeguridadSeguridad de RedesRespuesta a Incidentes
GitHub

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
anthropic-experimental/sandbox-runtime

sandbox-runtime

Una herramienta de sandboxing ligera para aplicar restricciones de sistema de archivos y red en procesos arbitrarios a nivel del sistema operativo, sin necesidad de un contenedor.

Ver Repositorio
4.9k399150hace 1 díaRevisado por Kitploit
Compartir
# Anthropic Sandbox Runtime (srt)

Una herramienta de sandboxing ligera para aplicar restricciones de sistema de archivos y de red a procesos arbitrarios a nivel del sistema operativo, sin necesidad de un contenedor.

`srt` utiliza primitivas nativas de sandboxing del sistema operativo (`sandbox-exec` en macOS, `bubblewrap` en Linux) y filtrado de red basado en proxy. Puede usarse para aplicar sandboxing al comportamiento de agentes, servidores MCP locales, comandos bash y procesos arbitrarios.

> **Vista previa de investigación Beta**
>
> El Sandbox Runtime es una vista previa de investigación desarrollada para [Claude Code](https://www.claude.com/product/claude-code) con el fin de permitir agentes de IA más seguros. Se pone a disposición como una vista previa temprana de código abierto para ayudar al ecosistema en general a construir sistemas agénticos más seguros. Dado que se trata de una vista previa de investigación temprana, las APIs y los formatos de configuración pueden evolucionar. ¡Agradecemos los comentarios y las contribuciones para hacer que los agentes de IA sean más seguros por defecto!

## Instalación

```bash
npm install -g @anthropic-ai/sandbox-runtime
```

## Uso básico

```bash
# Network restrictions
$ srt "curl anthropic.com"
Running: curl anthropic.com
<html>...</html>  # Request succeeds

$ srt "curl example.com"
Running: curl example.com
Connection blocked by network allowlist  # Request blocked

# Filesystem restrictions
$ srt "cat README.md"
Running: cat README.md
# Anthropic Sandb...  # Current directory access allowed

$ srt "cat ~/.ssh/id_rsa"
Running: cat ~/.ssh/id_rsa
cat: /Users/ollie/.ssh/id_rsa: Operation not permitted  # Specific file blocked
```

## Descripción general

Este paquete proporciona una implementación de sandbox autónoma que puede utilizarse tanto como herramienta CLI como biblioteca. Está diseñado con una filosofía **segura por defecto** adaptada a los casos de uso habituales de los desarrolladores: los procesos se inician con acceso mínimo y solo se abren explícitamente los huecos que se necesitan.

**Capacidades clave:**

- **Restricciones de red**: controla qué hosts/dominios pueden ser accedidos mediante HTTP/HTTPS y otros protocolos
- **Restricciones del sistema de archivos**: controla qué archivos/directorios pueden leerse/escribirse
- **Restricciones de sockets Unix**: controla el acceso a sockets IPC locales
- **Monitorización de violaciones**: en macOS, accede al almacén de registros de violaciones del sandbox del sistema para alertas en tiempo real

### Caso de uso de ejemplo: sandboxing de servidores MCP

Un caso de uso clave es el sandboxing de servidores del Model Context Protocol (MCP) para restringir sus capacidades. Por ejemplo, para aplicar sandbox al servidor MCP de sistema de archivos:

**Sin sandboxing** (`.mcp.json`):

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem"]
    }
  }
}
```

**Con sandboxing** (`.mcp.json`):

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "srt",
      "args": ["npx", "-y", "@modelcontextprotocol/server-filesystem"]
    }
  }
}
```

Luego configure las restricciones en `~/.srt-settings.json`:

```json
{
  "filesystem": {
    "denyRead": [],
    "allowWrite": ["."],
    "denyWrite": ["~/sensitive-folder"]
  },
  "network": {
    "allowedDomains": [],
    "deniedDomains": []
  }
}
```

Ahora el servidor MCP tendrá bloqueada la escritura en la ruta denegada:

```
> Write a file to ~/sensitive-folder
✗ Error: EPERM: operation not permitted, open '/Users/ollie/sensitive-folder/test.txt'
```

## Cómo funciona

El sandbox utiliza primitivas a nivel de sistema operativo para aplicar restricciones que se aplican a todo el árbol de procesos:

- **macOS**: utiliza `sandbox-exec` con [perfiles Seatbelt](https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf) generados dinámicamente
- **Linux**: utiliza [bubblewrap](https://github.com/containers/bubblewrap) para la contenedorización con aislamiento de espacio de nombres de red
- **Windows**: ejecuta el proceso en sandbox bajo una cuenta de usuario local dedicada `srt-sandbox`, con una barrera de salida de [Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/windows-filtering-platform-start-page) vinculada al SID de esa cuenta, un token con restricción de escritura y ACEs explícitas en el árbol de trabajo

0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305

### Modelo de aislamiento dual

Tanto el aislamiento del sistema de archivos como el de red son necesarios para un sandboxing eficaz. Sin aislamiento de archivos, un proceso comprometido podría exfiltrar claves SSH u otros archivos sensibles. Sin aislamiento de red, un proceso podría escapar del sandbox y obtener acceso de red sin restricciones.

**Aislamiento del sistema de archivos** aplica restricciones de lectura y escritura:

- **Lectura** (patrón denegar-luego-permitir): de forma predeterminada, el acceso de lectura está permitido en todas partes. Puede denegar regiones amplias (p. ej., `/Users`) y luego volver a permitir rutas específicas dentro de ellas (p. ej., `.`). `allowRead` tiene precedencia sobre `denyRead` — lo contrario de la escritura, donde `denyWrite` tiene precedencia sobre `allowWrite`. Una entrada `denyRead` que sea más específica que la región `allowRead` en la que se encuentra (p. ej. `denyRead: ["**/.env"]` o `["./secrets"]` con `allowRead: ["."]`) sigue permaneciendo denegada.
- **Escritura** (patrón solo-permitir): de forma predeterminada, el acceso de escritura está denegado en todas partes. Debe permitir rutas explícitamente (p. ej., `.`, `/tmp`). Una lista de permisos vacía significa que no hay acceso de escritura.

**Aislamiento de red** (patrón solo-permitir): de forma predeterminada, todo el acceso de red está denegado. Debe permitir dominios explícitamente. Una lista allowedDomains vacía significa que no hay acceso de red. El tráfico de red se enruta a través de servidores proxy que se ejecutan en el host:

- **Linux**: las solicitudes se enrutan a través del sistema de archivos mediante un socket de dominio Unix. El espacio de nombres de red del proceso en sandbox se elimina por completo, por lo que todo el tráfico de red debe pasar por los proxies que se ejecutan en el host (escuchando en sockets Unix que se montan mediante bind dentro del sandbox)

- **macOS**: el perfil Seatbelt permite la comunicación solo a un puerto localhost específico. Los proxies escuchan en este puerto, creando un canal controlado para todo el acceso de red

- **Windows**: un conjunto de filtros WFP para toda la máquina bloquea las conexiones salientes realizadas por procesos que se ejecutan como la cuenta `srt-sandbox`, excepto el loopback al rango de puertos del proxy. Los proxies escuchan dentro de ese rango, creando un canal controlado para todo el acceso de red. Los filtros no siguen a un proceso en sandbox que coloque un token diferente en un hilo antes de crear un socket, ni al tráfico que un servicio del sistema transporta en su nombre; consulte las [limitaciones conocidas](#known-limitations) de Windows

Tanto el tráfico HTTP/HTTPS (a través del proxy HTTP) como el resto del tráfico TCP (a través del proxy SOCKS5) son mediados por estos proxies, que aplican sus listas de dominios permitidos y denegados.

Para obtener más detalles sobre el sandboxing en Claude Code, consulte:

- [Documentación de sandboxing de Claude Code](https://docs.claude.com/en/docs/claude-code/sandboxing)
- [Beyond Permission Prompts: Making Claude Code More Secure and Autonomous](https://www.anthropic.com/engineering/claude-code-sandboxing)

## Arquitectura

```
src/
├── index.ts                  # Library exports
├── cli.ts                    # CLI entrypoint (srt command)
├── utils/                    # Shared utilities
│   ├── debug.ts             # Debug logging
│   ├── settings.ts          # Settings reader (permissions + sandbox config)
│   ├── platform.ts          # Platform detection
│   └── exec.ts              # Command execution utilities
└── sandbox/                  # Sandbox implementation
    ├── sandbox-manager.ts    # Main sandbox manager
    ├── sandbox-schemas.ts    # Zod schemas for validation
    ├── sandbox-violation-store.ts # Violation tracking
    ├── sandbox-utils.ts      # Shared sandbox utilities
    ├── http-proxy.ts         # HTTP/HTTPS proxy for network filtering
    ├── socks-proxy.ts        # SOCKS5 proxy for network filtering
    ├── linux-sandbox-utils.ts # Linux bubblewrap sandboxing
    ├── macos-sandbox-utils.ts # macOS sandbox-exec sandboxing
    └── windows-sandbox-utils.ts # Windows srt-win sandboxing
```

## Uso

### Como herramienta CLI

El comando `srt` (Anthropic Sandbox Runtime) envuelve cualquier comando con límites de seguridad:

```bash
# Run a command in the sandbox
srt echo "hello world"

# With debug logging
srt --debug curl https://example.com

# Specify custom settings file
srt --settings /path/to/srt-settings.json npm install
```

El archivo de configuración es opcional: sin ningún archivo en `~/.srt-settings.json`, `srt` se ejecuta con los valores predeterminados integrados: sin acceso a la red, sin escrituras fuera de las rutas de escritura predeterminadas y lecturas sin restricciones. Un archivo de configuración que _sí_ está presente pero está vacío, no se puede leer o no se valida es un error: `srt` lo indica y sale en lugar de recurrir a esos valores predeterminados, que son una configuración distinta en lugar de una más débil; recurrir a ellos descartaría las reglas `denyRead`, `allowRead` y de credenciales del archivo, junto con todo lo demás que indicaba. Lo mismo ocurre con un archivo nombrado con `--settings`, que también debe existir.

#### Actualizar la configuración mientras se ejecuta el comando: `--control-fd`

`--control-fd <fd>` lee actualizaciones de configuración desde un descriptor que el llamador ya ha abierto, un objeto JSON por línea con la misma forma que el archivo de configuración. Cada línea reemplaza toda la configuración y se valida contra el mismo esquema, por lo que una línea es una configuración completa en lugar de un parche: `network` y `filesystem` son obligatorios, y una clave que la línea omite vuelve a su valor predeterminado.

```bash
# fd 3 is the read end of a pipe the caller writes lines to
srt --control-fd 3 -- npm test
```

Lo que cambia una línea aceptada una vez que el comando está en ejecución:

- Las listas de red — `network.allowedDomains`, `deniedDomains` (con
  `deniedDomainReasons`) y `deniedResolvedAddresses` — surten efecto en la
  siguiente conexión, en todas las plataformas: el proxy las consulta por
  petición, y la comprobación de direcciones resueltas se reconstruye a partir
  de la misma línea. Lo mismo ocurre con `network.mitmProxy` y
  `network.tlsTerminate.excludeDomains`, que también lee por petición.
- `credentials.sigv4` surte efecto en la siguiente petición, siempre que srt
  se haya iniciado con un bloque `credentials`: el hook de firma solo se
  instala entonces, y lee las políticas por petición en lugar de capturarlas.
- Nada más cambia. Las reglas del sistema de archivos ya están en el perfil
  de seatbelt, en el argv de bubblewrap o en las ACEs de Windows, las máscaras
  de credenciales se construyeron cuando se envolvió el comando, y los
  servidores proxy en ejecución capturaron `network.parentProxy`, y si se
  termina TLS o no, cuando arrancaron.
- En Windows, srt detecta una línea cuyo conjunto de acceso a archivos
  (`filesystem.*` junto con `credentials.files`) difiere del aplicado al
  inicio, y lo indica solo bajo `SRT_DEBUG`: la concesión de ACL es de ámbito
  de sesión, por lo que el conjunto aplicado al inicio sigue vigente. El resto
  de la línea se aplica como se describe arriba.

Cómo lee srt el canal, y qué rechaza:

- El descriptor debe ser un entero **3 o superior** y legible — `0`-`2`
  son los flujos estándar. srt sale con un error en lugar de ejecutar el
  comando cuando no puede leer el descriptor que se le dio, de modo que un
  canal muerto nunca pasa por uno vivo. Un canal que muere antes de haber
  entregado una sola actualización se lleva consigo el comando; uno que muere
  después lo indica y deja el comando en ejecución bajo la configuración
  aplicada por última vez.
- Una línea que no es una configuración válida se reporta en stderr y se
  descarta; la configuración anterior sigue vigente. La línea en sí va al log
  de depuración en lugar de a la terminal, y una línea en blanco se ignora
  silenciosamente.
- srt empieza a leer solo una vez que el sandbox está activo, por lo que una
  actualización escrita antes de ese momento espera en el canal en lugar de
  perderse — y no puede ser sobrescrita por la configuración con la que
  arranca el sandbox. Tal línea puede leerse mientras el comando aún se está
  envolviendo, y es entonces la configuración con la que se envuelve, incluidas
  las reglas del sistema de archivos. Que se lea tan pronto depende de cuánto
  tarde el envolvimiento (en Linux, un glob de denegación sobre un árbol
  grande es suficiente), por lo que una regla bajo la que el comando debe
  arrancar pertenece al archivo de configuración.
- srt **sale con el comando envuelto** y no espera a que el escritor cierre
  el descriptor. El fin de la entrada tampoco es un error: el comando sigue
  en ejecución bajo la configuración aplicada por última vez.
- Dele a srt un **extremo dedicado y de solo lectura**. srt pone un pipe o
  socket en modo no bloqueante, y ese flag reside en la descripción de archivo
  abierta, por lo que cualquier otra cosa que mantenga la misma descripción —
  un `exec 3<fifo` de un shell, un `pass_fds` de un descriptor que el padre
  sigue usando — recibe `EAGAIN` en sus propias lecturas bloqueantes a partir
  de entonces.
- En macOS y Linux el comando en sandbox no recibe el descriptor: srt apunta
  esa ranura a `/dev/null` para el comando, de modo que nada dentro del
  sandbox puede leer las actualizaciones ni escribir una configuración propia.
  En Windows el comando se lanza solo con los tres flujos estándar, por lo que
  el descriptor de control no está entre los descriptores que se le entregan.

### Como proxy independiente con un decisor externo: `srt proxy`

`srt proxy` (o el ejecutable de archivo único `srt-proxy` generado por `bun run build:srt-proxy`) ejecuta solo el proxy HTTP de SRT, sin ningún proceso hijo en sandbox, para un host que ejecuta la carga de trabajo en otro lugar. Acepta en un socket de escucha que el host le entrega, termina cada CONNECT en el propio proceso, y reenvía una petición solo cuando un proceso decisor separado, alcanzado a través de otro descriptor heredado, lo permite. Consulte [docs/srt-proxy.md](https://github.com/anthropic-experimental/sandbox-runtime/blob/main/docs/srt-proxy.md) para la línea de comandos, el protocolo del decisor y el modelo de seguridad.

### Como biblioteca

```typescript
import {
  SandboxManager,
  type SandboxRuntimeConfig,
} from '@anthropic-ai/sandbox-runtime'
import { spawn } from 'child_process'

// Define your sandbox configuration
const config: SandboxRuntimeConfig = {
  network: {
    allowedDomains: ['example.com', 'api.github.com'],
    deniedDomains: [],
  },
  filesystem: {
    denyRead: ['~/.ssh'],
    allowWrite: ['.', '/tmp'],
    denyWrite: ['.env'],
  },
}

// Initialize the sandbox (starts proxy servers, etc.)
await SandboxManager.initialize(config)

// Wrap a command with sandbox restrictions
const sandboxedCommand = await SandboxManager.wrapWithSandbox(
  'curl https://example.com',
)

// Execute the sandboxed command
const child = spawn(sandboxedCommand, { shell: true, stdio: 'inherit' })

// Handle exit and cleanup after child process completes
child.on('exit', async code => {
  console.log(`Command exited with code ${code}`)
  // Cleanup when done (optional, happens automatically on process exit)
  await SandboxManager.reset()
})
```

**Atribución de infracciones (`commandId` / `commandText`).** Las infracciones observadas mientras se ejecuta un comando envuelto (líneas de registro de seatbelt, eventos de seccomp, denegaciones del proxy) se almacenan bajo una clave de atribución, y `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` las buscan mediante esa misma clave. De forma predeterminada, la clave es la propia cadena envuelta. Pase un `commandId` opaco por invocación (p. ej., un id de uso de herramienta) para usar ese como clave en su lugar — recomendado: las claves se comparan por sus primeros 100 caracteres, por lo que comandos largos que comparten un prefijo se atribuirían de forma cruzada, y una reejecución del mismo texto heredaría los eventos de la ejecución anterior. Si la cadena que _ejecuta_ no es el comando que la invocación _representa_ (p. ej., envuelve un `source <snapshot> && eval '<cmd>'` ensamblado), pase también `commandText: '<cmd>'`: es contra lo que se comparan los patrones de comando de `ignoreViolations` y lo que cada infracción reporta como su `command`. Un `commandId` que pase a `wrapWithSandbox` debe ser la misma cadena no vacía que luego pase a `annotateStderrWithSandboxFailures` / `getViolationsForCommand`; uno vacío se trata como si no hubiera `commandId` en absoluto, por lo que la clave es el comando.

Solo la clave se recorta a 100 caracteres. A partir de la v0.0.76, el `command` reportado — y el texto contra el que se comparan los patrones de comando de `ignoreViolations` — es el comando completo para una invocación envuelta sin un `commandId`, no sus primeros 100 caracteres; por lo tanto, un patrón solo puede suprimir más de lo que lo hacía antes, nunca menos. Una clave de atribución que ninguna invocación de este proceso registró (los portadores son escribibles desde dentro del sandbox) se reporta saneada y recortada a esa misma longitud de clave.

```typescript
const wrapped = await SandboxManager.wrapWithSandbox(
  assembledCommand, // what actually runs
  undefined,
  undefined,
  undefined,
  { commandId: invocationId, commandText: rawCommand },
)
// ... run it ...
const annotated = SandboxManager.annotateStderrWithSandboxFailures(
  invocationId,
  stderr,
)
```

**Consultar sobre un host que ninguna regla decide (el callback ask).** El segundo argumento de `SandboxManager.initialize` es un `SandboxAskCallback` opcional. Se consulta sobre un destino que ni `network.deniedDomains`, ni `network.allowedDomains`, ni una lista de permitidos por comando (siguiente sección) decidieron, y nunca se consulta bajo `network.strictAllowlist`. Sin un callback, dicho destino se deniega. El callback se resuelve en uno de los siguientes valores:

- `true` - permite la conexión. Solo el valor `true` permite.
- `false` - la deniega. La línea de violación informa el motivo genérico `user denied`.
- `{ allow: false, reason: '...' }` - la deniega e informa `reason` en la línea de violación en lugar del texto genérico, de modo que quien lea el bloque `<sandbox_violations>` (incluido un modelo) sepa por qué y qué hacer en su lugar. El cliente en sandbox también lo lee, como la frase de estado del `403` que responde a su CONNECT.

Cualquier otra respuesta deniega, sea truthy o no, e informa el motivo genérico. Eso incluye un objeto que lleva un `reason` sin decir `allow: false`, como `{ allow: true, reason: '...' }`: su motivo no se informa.

El motivo se sanea antes de almacenarse, igual que el resto de una línea de violación. Cada secuencia de caracteres de control (saltos de línea y tabulaciones incluidos) o de caracteres invisibles (caracteres de ancho cero, el joiner entre ellos, y controles bidi) se convierte en un espacio; `<` y `>` se eliminan, así que `re-run with <host> listed` se almacena como `re-run with host listed`; los extremos se recortan. El resultado se corta a 500 caracteres, contados como unidades de código UTF-16 tal como las cuenta `String.prototype.length`. Un motivo que no deja nada tras eso recurre a `user denied`. Escríbelo como una sola línea de texto plano.

**Cambio de comportamiento en la primera versión posterior a 0.0.79:** el filtro solía permitir ante cualquier respuesta truthy, así que un callback que se resolvía en un valor truthy distinto de `true` (`1`, una cadena, cualquier objeto) permitía la conexión. Ahora la deniega. Por la misma razón, `{ allow: false, reason }` devuelto a una versión anterior se leería allí como un permiso, porque un objeto es truthy. `SandboxManager.askCallbackDenyReason` es `true` en una versión que entiende el objeto: compruébalo antes de devolver uno, y deniega con un `false` simple donde no esté presente.

```typescript
const deny = (reason: string) =>
  SandboxManager.askCallbackDenyReason
    ? { allow: false as const, reason }
    : false

await SandboxManager.initialize(config, async ({ host, port }) => {
  if (await userApproves(host, port)) return true
  return deny(`${host} was not approved for this session`)
})
```

**Listas de permitidos de red por comando (`registerCommandNetworkLists`).** Una invocación puede llevar su propia lista de permitidos, además de la configurada, mientras se ejecuta:

```typescript
import { randomBytes } from 'node:crypto'

// 128 bits of randomness, 22 characters. See below for why nothing less will do.
const commandId = randomBytes(16).toString('base64url')
const wrapped = await SandboxManager.wrapWithSandbox(
  command,
  undefined,
  undefined,
  undefined,
  { commandId },
)

SandboxManager.registerCommandNetworkLists(commandId, {
  allowedDomains: ['registry.example.org', '*.cdn.example.org:443'],
})
const child = spawn(wrapped, { shell: true })
const unregister = () => SandboxManager.unregisterCommandNetworkLists(commandId)
child.once('exit', unregister)
child.once('error', unregister) // the child never started
```

Las entradas usan la gramática y el emparejador de `network.allowedDomains` y reciben la misma validación. `registerCommandNetworkLists` lanza una excepción ante una entrada no válida y ante un `commandId` de menos de 22 caracteres (un sustituto no emparejado no cuenta). Registrar un id de nuevo reemplaza su lista; `unregisterCommandNetworkLists` no hace nada para un id que no tiene ninguna; `reset()` elimina todos los registros.

El orden de evaluación para una conexión es:

1. una coincidencia en `network.deniedDomains` deniega;
2. una coincidencia en `network.allowedDomains` permite;
3. `network.strictAllowlist` deniega;
4. una coincidencia en la lista registrada para el id que presenta la conexión permite;
5. el callback de consulta decide si existe, y en caso contrario la conexión se deniega.

Por lo tanto, una entrada por comando nunca anula una entrada configurada en `deniedDomains`, y se ignora por completo bajo `strictAllowlist`. Tampoco entra nunca en `network.*`: `getConfig()` y `getNetworkRestrictionConfig()` no la muestran, y el ámbito `injectHosts` predeterminado de una credencial enmascarada, que es `network.allowedDomains`, no crece. Un host permitido de esta forma sigue pasando por la comprobación de dirección resuelta cuando se marca, y un literal IP en una lista por comando no añade ninguna exención allí.

Qué debe ser el id, y qué no es esta función: el proxy averigua a qué invocación pertenece una conexión a partir del nombre de usuario del proxy, y el nombre de usuario lo presenta el cliente dentro del sandbox. Por lo tanto, el id es lo **único** que vincula una conexión a una lista de permitidos. **Debe** ser impredecible: al menos 128 bits de aleatoriedad, nunca un contador, una marca de tiempo ni nada derivado del comando. Un proceso en sandbox que presenta el id de otra invocación activa obtiene los permisos de esa invocación, así que esto es atribución, no una frontera entre comandos concurrentes de una misma sesión. Registra justo antes de lanzar el comando envuelto, y anula el registro cuando el hijo termine o nunca llegue a iniciarse: un registro que sobrevive a su comando amplía la ventana en la que su id merece la pena ser presentado. Como con toda clave de atribución, solo participan los primeros 100 caracteres de un id. Mantén los ids en ASCII: una lista bajo un id no ASCII cuya forma codificada no quepa en el nombre de usuario del proxy (255 bytes) se registra y nunca se aplica.

Ninguna lista se aplica mientras `network.httpProxyPort` nombre un proxy externo: el wrap no da nombre de usuario a ese proxy, así que ninguna conexión lleva un id. `registerCommandNetworkLists` sigue teniendo éxito (y lo indica en una línea bajo `SRT_DEBUG`), y cada conexión se decide como si no existiera ninguna lista.

#### Exportaciones disponibles

```typescript
// Main sandbox manager
export { SandboxManager } from '@anthropic-ai/sandbox-runtime'

// Violation tracking
export { SandboxViolationStore } from '@anthropic-ai/sandbox-runtime'

// TypeScript types
export type {
  SandboxRuntimeConfig,
  NetworkConfig,
  FilesystemConfig,
  IgnoreViolationsConfig,
  SandboxAskCallback,
  FsReadRestrictionConfig,
  FsWriteRestrictionConfig,
  NetworkRestrictionConfig,
} from '@anthropic-ai/sandbox-runtime'
```

## Configuración

### Ubicación del archivo de configuración

De forma predeterminada, el entorno de ejecución del sandbox busca la configuración en `~/.srt-settings.json`. Puede especificar una ruta personalizada utilizando el indicador `--settings`:

```bash
srt --settings /path/to/srt-settings.json <command>
```

### Ejemplo de configuración completa

```json
{
  "network": {
    "allowedDomains": [
      "github.com",
      "*.github.com",
      "lfs.github.com",
      "api.github.com",
      "npmjs.org",
      "*.npmjs.org"
    ],
    "deniedDomains": ["malicious.com"],
    "allowUnixSockets": ["/var/run/docker.sock"],
    "allowLocalBinding": false
  },
  "filesystem": {
    "denyRead": ["~/.ssh"],
    "allowRead": [],
    "allowWrite": [".", "src/", "test/", "/tmp"],
    "denyWrite": [".env", "config/production.json"]
  },
  "ignoreViolations": {
    "*": ["/usr/bin", "/System"],
    "git push": ["/usr/bin/nc"],
    "npm": ["/private/tmp"]
  },
  "enableWeakerNestedSandbox": false,
  "allowNestedUserNamespaces": false,
  "enableWeakerNetworkIsolation": false,
  "allowAppleEvents": false
}
```

### Opciones de configuración

#### Configuración de red

Utiliza un **patrón de solo permitidos** — todo acceso a la red está denegado por defecto.

- `network.allowedDomains` - Array de dominios permitidos (admite comodines como `*.example.com`). Array vacío = sin acceso a la red. Un sufijo opcional `:port` (`api.example.com:443`, `*.example.com:8443`) restringe una entrada a ese puerto de destino; las entradas sin puerto coinciden con cualquier puerto.
  - Los literales IPv6 deben ir entre corchetes, al estilo RFC 3986: `[::1]`, `[2001:db8::1]:443`. Una entrada sin corchetes con varios dos puntos se rechaza por ambigua (`2001:db8::1:443` es en sí misma una dirección válida).
- `network.deniedDomains` - Array de dominios denegados (se comprueba primero, tiene precedencia sobre allowedDomains). Mismo sufijo `:port`, y se acepta un `*` simple (o `*:22`) para denegar todo.
- `network.deniedDomainReasons` - Mapa opcional de una entrada de `deniedDomains` (coincidencia por cadena exacta) a un motivo orientado al modelo que aparece en la línea `<sandbox_violations>` cuando esa entrada deniega una conexión — indica qué está bloqueado y la alternativa autorizada (p. ej. `{"github.com:22": "SSH pushes to GitHub are blocked; use an https:// remote"}`). Las entradas sin motivo informan uno genérico. Para destinos SSH (puerto 22), el motivo también se entrega en banda: un cliente SSH tunelizado mediante un ProxyCommand SOCKS sin autenticación (p. ej. `nc -X 5` de BSD) recibe una desconexión SSH previa al intercambio de claves cuya descripción es el motivo, que OpenSSH imprime literalmente — mantén esos motivos por debajo de ~400 caracteres ASCII, con el imperativo primero, ya que OpenSSH trunca y escapa los caracteres no ASCII. Un cliente que sí se autentica, como hace el `GIT_SSH_COMMAND` que inyecta srt, recibe el motivo en cualquier puerto como la frase de estado del `403` que responde a su CONNECT, que es lo que imprime ese comando, y muchos clientes HTTP. Allí se limpia y recorta como en la línea de violación, y cada carácter no ASCII se convierte en `?`, ya que los clientes no coinciden en cómo leer uno en una línea de estado.
- `network.allowLocalBinding` - Permite que los comandos en sandbox usen puertos locales directamente (booleano, por defecto: false). macOS: enlazar y aceptar en cualquier puerto local, y conectar a `localhost` en cualquier puerto. Windows: conectar a direcciones de loopback en cualquier puerto TCP o UDP; forma parte de la instalación para toda la máquina, véase [Servidores locales en Windows](#local-servers-on-windows). Linux: se ignora — el sandbox tiene su propio espacio de nombres de red, cuyo loopback siempre es utilizable y no es el del host.

**Comprobación de direcciones resueltas.** Las listas de permitidos/denegados coinciden por _nombre_, pero quien controle el DNS de un nombre permitido (o de cualquier etiqueta bajo un comodín permitido) controla a qué resuelve. Por eso, antes de marcar un **nombre de host** permitido directamente, el proxy lo resuelve una vez, descarta cualquier dirección de un conjunto denegado y conecta a una dirección superviviente (la dirección que pasó la comprobación es la que se marca — no hay una segunda consulta). Si no sobrevive ninguna, la conexión se rechaza como cualquier otra denegación de política: HTTP/CONNECT reciben `403` (`X-Proxy-Error: blocked-by-sandbox-runtime`, el motivo en el cuerpo y, para un CONNECT, como frase de estado), SOCKS recibe "connection not allowed by ruleset", y se registra en el almacén de violaciones una línea `deny network-outbound host:port (resolved to a loopback address)` — que nombra la clase de dirección (loopback, link-local, de este host, metadatos de la nube, en lista de denegados, en lista, …), no la dirección en sí, que solo lleva el registro de depuración.

El conjunto denegado es: loopback (`127.0.0.0/8`, `::1`), no especificada (`0.0.0.0/8`, `::`), link-local (`169.254.0.0/16`, `fe80::/10`), multicast (`224.0.0.0/4`, `ff00::/8`), broadcast, los endpoints de metadatos de instancia en la nube / de plataforma que residen fuera de link-local (`100.100.100.200`, `168.63.129.16`, `192.0.0.192`, `fd00:ec2::/32`, `fd20:ce::254`, `fd00:c1::a9fe:a9fe`, `fd00:42::42`), cada dirección asignada actualmente a una de las interfaces de red de este propio host (un servicio vinculado a `0.0.0.0` responde en la LAN o en la dirección global exactamente igual que en loopback), cada literal IP listado en `deniedDomains` (respetando su `:port` si lo tiene), y cualquier cosa en `deniedResolvedAddresses`. Las entradas IPv4 también coinciden con las formas IPv6 que portan una dirección IPv4 — las direcciones IPv4-mapped, IPv4-compatible e IPv4-translated, el prefijo conocido de NAT64 (`64:ff9b::/96`) y 6to4 (`2002::/16`) se juzgan por la dirección IPv4 que embeben. El prefijo NAT64 de uso local `64:ff9b:1::/48` y los prefijos específicos de red no se decodifican — su disposición (la RFC 6052 permite la IPv4 en varias posiciones) no puede reconocerse a partir de la dirección sola; en una red así, liste las traducciones del prefijo de los rangos que deniega (p. ej. `<prefix>::a00:0/104` para `10.0.0.0/8`). Las direcciones que alcanzan este host sin estar asignadas a él — la dirección pública 1:1-NAT de una instancia en la nube, un port-forward de un router, un alias de host-gateway de un contenedor o VM — no se cubren automáticamente; lístelas en `deniedResolvedAddresses`.

---

[Read more](https://github.com/anthropic-experimental/sandbox-runtime)
Descargar herramienta