Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
sandbox-runtime — Uma ferramenta leve de sandboxing para aplicar restrições de sistema de arquivos e rede em processos arbitrários no nível do sistema operacional, sem exigir um contêiner. | Kitploit
Ferramentas/GitHubGitHub/anthropic-experimental/sandbox-runtime
Ferramentas DefensivasSegurança de ContêineresAnálise Dinâmica (Sandboxing)Auditoria de ConfiguraçãoVirtualização para SegurançaSegurança de RedeResposta a Incidentes
GitHub

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
anthropic-experimental/sandbox-runtime

sandbox-runtime

Uma ferramenta leve de sandboxing para aplicar restrições de sistema de arquivos e rede em processos arbitrários no nível do sistema operacional, sem exigir um contêiner.

Ver Repositório
4.9k399150há 1 diaRevisado pelo Kitploit
Compartilhar
# Anthropic Sandbox Runtime (srt)

Uma ferramenta de sandbox leve para impor restrições de sistema de arquivos e de rede a processos arbitrários no nível do sistema operacional, sem exigir um contêiner.

`srt` usa primitivas nativas de sandbox do sistema operacional (`sandbox-exec` no macOS, `bubblewrap` no Linux) e filtragem de rede baseada em proxy. Pode ser usado para colocar em sandbox o comportamento de agentes, servidores MCP locais, comandos bash e processos arbitrários.

> **Prévia de Pesquisa Beta**
>
> O Sandbox Runtime é uma prévia de pesquisa desenvolvida para o [Claude Code](https://www.claude.com/product/claude-code) para viabilizar agentes de IA mais seguros. Está sendo disponibilizado como uma prévia inicial de código aberto para ajudar o ecossistema mais amplo a construir sistemas agênticos mais seguros. Como esta é uma prévia inicial de pesquisa, as APIs e os formatos de configuração podem evoluir. Agradecemos feedback e contribuições para tornar os agentes de IA mais seguros por padrão!

## Instalação

```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
```

## Visão Geral

Este pacote fornece uma implementação de sandbox autônoma que pode ser usada tanto como ferramenta CLI quanto como biblioteca. Ele foi projetado com uma filosofia **segura por padrão** adaptada aos casos de uso comuns de desenvolvedores: os processos iniciam com acesso mínimo, e você abre explicitamente apenas os buracos de que precisa.

**Principais capacidades:**

- **Restrições de rede**: Controle quais hosts/domínios podem ser acessados via HTTP/HTTPS e outros protocolos
- **Restrições de sistema de arquivos**: Controle quais arquivos/diretórios podem ser lidos/escritos
- **Restrições de sockets Unix**: Controle o acesso a sockets IPC locais
- **Monitoramento de violações**: No macOS, acesse o armazenamento de logs de violações de sandbox do sistema para alertas em tempo real

### Exemplo de Caso de Uso: Sandboxing de Servidores MCP

Um caso de uso importante é o sandboxing de servidores Model Context Protocol (MCP) para restringir suas capacidades. Por exemplo, para colocar o servidor MCP de sistema de arquivos em sandbox:

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

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

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

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

Em seguida, configure as restrições em `~/.srt-settings.json`:

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

Agora o servidor MCP ficará bloqueado de escrever no caminho negado:

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

## Como Funciona

O sandbox utiliza primitivas de nível de sistema operacional para impor restrições que se aplicam a toda a árvore de processos:

- **macOS**: Utiliza `sandbox-exec` com [perfis Seatbelt](https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf) gerados dinamicamente
- **Linux**: Utiliza [bubblewrap](https://github.com/containers/bubblewrap) para containerização com isolamento de namespace de rede
- **Windows**: Executa o processo em sandbox sob uma conta de usuário local dedicada `srt-sandbox`, com uma cerca de saída do [Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/windows-filtering-platform-start-page) vinculada ao SID dessa conta, um token com restrição de escrita e ACEs explícitas na árvore de trabalho

0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305

### Modelo de Isolamento Duplo

Tanto o isolamento de sistema de arquivos quanto o de rede são necessários para um sandboxing eficaz. Sem isolamento de arquivos, um processo comprometido poderia exfiltrar chaves SSH ou outros arquivos sensíveis. Sem isolamento de rede, um processo poderia escapar do sandbox e obter acesso irrestrito à rede.

**Isolamento de Sistema de Arquivos** impõe restrições de leitura e escrita:

- **Leitura** (padrão negar-então-permitir): Por padrão, o acesso de leitura é permitido em todos os lugares. Você pode negar regiões amplas (por exemplo, `/Users`) e então permitir novamente caminhos específicos dentro delas (por exemplo, `.`). `allowRead` tem precedência sobre `denyRead` — o oposto da escrita, onde `denyWrite` tem precedência sobre `allowWrite`. Uma entrada `denyRead` mais específica do que a região `allowRead` na qual ela se encontra (por exemplo, `denyRead: ["**/.env"]` ou `["./secrets"]` com `allowRead: ["."]`) permanece negada.
- **Escrita** (padrão apenas-permitir): Por padrão, o acesso de escrita é negado em todos os lugares. Você deve permitir explicitamente caminhos (por exemplo, `.`, `/tmp`). Uma lista de permissões vazia significa nenhum acesso de escrita.

**Isolamento de Rede** (padrão apenas-permitir): Por padrão, todo o acesso à rede é negado. Você deve permitir domínios explicitamente. Uma lista allowedDomains vazia significa nenhum acesso à rede. O tráfego de rede é roteado através de servidores proxy em execução no host:

- **Linux**: As requisições são roteadas via sistema de arquivos através de um socket de domínio Unix. O namespace de rede do processo em sandbox é removido completamente, então todo o tráfego de rede deve passar pelos proxies em execução no host (escutando em sockets Unix que são montados por bind no sandbox)

- **macOS**: O perfil Seatbelt permite comunicação apenas para uma porta localhost específica. Os proxies escutam nessa porta, criando um canal controlado para todo o acesso à rede

- **Windows**: Um conjunto de filtros WFP de âmbito de máquina bloqueia conexões de saída feitas por processos em execução como a conta `srt-sandbox`, exceto loopback para a faixa de portas do proxy. Os proxies escutam dentro dessa faixa, criando um canal controlado para todo o acesso à rede. Os filtros não acompanham um processo em sandbox que coloca um token diferente em uma thread antes de criar um socket, nem o tráfego que um serviço do sistema transporta em seu nome; consulte as [Limitações conhecidas](#known-limitations) do Windows

Tanto HTTP/HTTPS (via proxy HTTP) quanto outro tráfego TCP (via proxy SOCKS5) são mediados por esses proxies, que impõem suas listas de permissões e negações de domínios.

Para mais detalhes sobre sandboxing no Claude Code, consulte:

- [Documentação de Sandboxing do 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)

## Arquitetura

```
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 ferramenta CLI

O comando `srt` (Anthropic Sandbox Runtime) envolve qualquer comando com limites de segurança:

```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
```

O arquivo de configurações é opcional — sem nenhum arquivo em `~/.srt-settings.json`, o `srt` é executado com os padrões internos: sem acesso à rede, sem gravações fora dos caminhos de escrita padrão e leituras irrestritas. Um arquivo de configurações que _esteja_ presente mas vazio, que não possa ser lido ou que não seja válido é um erro: o `srt` informa isso e encerra em vez de recorrer a esses padrões, que são uma configuração diferente e não uma versão mais fraca — recorrer a eles descartaria as regras `denyRead`, `allowRead` e de credenciais do arquivo, juntamente com tudo o mais que ele declarava. O mesmo vale para um arquivo indicado com `--settings`, que também precisa existir.

#### Atualizando a configuração enquanto o comando é executado: `--control-fd`

`--control-fd <fd>` lê atualizações de configuração a partir de um descritor que o chamador já abriu, um objeto JSON por linha no mesmo formato do arquivo de configurações. Cada linha substitui toda a configuração e é validada segundo o mesmo esquema, portanto uma linha é uma configuração completa e não um patch: `network` e `filesystem` são obrigatórios, e uma chave omitida na linha volta ao seu valor padrão.

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

O que uma linha aceita altera quando o comando já está em execução:

- As listas de rede — `network.allowedDomains`, `deniedDomains` (com
  `deniedDomainReasons`) e `deniedResolvedAddresses` — entram em vigor na
  próxima conexão, em todas as plataformas: o proxy consulta-as por pedido,
  e a verificação de endereços resolvidos é reconstruída a partir da mesma
  linha. O mesmo acontece com `network.mitmProxy` e
  `network.tlsTerminate.excludeDomains`, que também são lidos por pedido.
- `credentials.sigv4` entra em vigor no próximo pedido, desde que o srt
  tenha arrancado com um bloco `credentials`: o hook de assinatura só é
  instalado nesse caso, e lê as políticas por pedido em vez de as capturar.
- Nada mais muda. As regras do sistema de ficheiros já estão no perfil do
  seatbelt, no argv do bubblewrap ou nas ACEs do Windows, as máscaras de
  credenciais foram construídas quando o comando foi envolvido, e os
  servidores proxy em execução capturaram `network.parentProxy`, e se o TLS
  é ou não terminado, quando arrancaram.
- No Windows, o srt deteta uma linha cujo conjunto de acesso a ficheiros
  (`filesystem.*` em conjunto com `credentials.files`) difere do aplicado no
  arranque, e só o indica sob `SRT_DEBUG`: a concessão de ACL é ao nível da
  sessão, pelo que o conjunto aplicado no arranque permanece em vigor. O
  resto da linha é aplicado como acima.

Como o srt lê o canal, e o que recusa:

- O descritor tem de ser um inteiro **3 ou superior** e legível — `0`-`2`
  são os fluxos padrão. O srt termina com erro em vez de executar o comando
  quando não consegue ler o descritor que lhe foi dado, pelo que um canal
  morto nunca passa por um canal vivo. Um canal que morre antes de ter
  entregue uma única atualização leva o comando consigo; um que morre depois
  avisa e deixa o comando a correr com a configuração aplicada por último.
- Uma linha que não seja uma configuração válida é reportada no stderr e
  descartada; a configuração anterior permanece em vigor. A própria linha vai
  para o registo de depuração em vez de para o terminal, e uma linha em
  branco é ignorada silenciosamente.
- O srt só começa a ler depois de a sandbox estar ativa, pelo que uma
  atualização escrita antes disso fica à espera no canal em vez de se perder
  — e não pode ser substituída pela configuração com que a sandbox arranca.
  Essa linha pode ser lida enquanto o comando ainda está a ser envolvido, e é
  então a configuração com que é envolvido, incluindo as regras do sistema de
  ficheiros. Se é lida assim tão cedo depende de quanto tempo o envolvimento
  demora (no Linux, um glob de negação sobre uma árvore grande é suficiente),
  pelo que uma regra sob a qual o comando tem de arrancar pertence ao ficheiro
  de definições.
- O srt **termina com o comando envolvido** e não espera que o escritor
  feche o descritor. O fim da entrada também não é um erro: o comando
  continua a correr com a configuração aplicada por último.
- Dê ao srt uma **extremidade dedicada e só de leitura**. O srt coloca um
  pipe ou socket em modo não bloqueante, e esse sinalizador reside na
  descrição de ficheiro aberta, pelo que qualquer outra coisa que detenha a
  mesma descrição — um `exec 3<fifo` de uma shell, um `pass_fds` de um
  descritor que o processo pai continua a usar — passa a receber `EAGAIN`
  nas suas próprias leituras bloqueantes a partir daí.
- No macOS e no Linux o comando em sandbox não recebe o descritor: o srt
  aponta essa posição para `/dev/null` para o comando, pelo que nada dentro
  da sandbox consegue ler as atualizações ou escrever uma configuração
  própria. No Windows o comando é lançado apenas com os três fluxos padrão,
  pelo que o descritor de controlo não está entre os descritores que lhe são
  entregues.

### Como proxy autónomo com um decisor externo: `srt proxy`

O `srt proxy` (ou o executável de ficheiro único `srt-proxy` construído por `bun run build:srt-proxy`) executa apenas o proxy HTTP do SRT, sem processo filho em sandbox, para um host que executa a carga de trabalho noutro local. Aceita ligações num socket de escuta que o host lhe entrega, termina cada CONNECT no próprio processo, e só encaminha um pedido quando um processo decisor separado, contactado através de outro descritor herdado, o permite. Consulte [docs/srt-proxy.md](https://github.com/anthropic-experimental/sandbox-runtime/blob/main/docs/srt-proxy.md) para a linha de comandos, o protocolo do decisor e o modelo de segurança.

### 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()
})
```

**Atribuição de violações (`commandId` / `commandText`).** As violações observadas enquanto um comando encapsulado é executado (linhas de log do seatbelt, eventos seccomp, negações do proxy) são armazenadas sob uma chave de atribuição, e `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` procuram-nas por essa mesma chave. Por predefinição, a chave é a própria string encapsulada. Passe um `commandId` opaco por invocação (por exemplo, um id de utilização de ferramenta) para usar esse como chave — recomendado: as chaves são comparadas pelos primeiros 100 caracteres, pelo que comandos longos que partilhem um prefixo seriam de outro modo atribuídos de forma cruzada, e uma reexecução do mesmo texto herdaria os eventos da execução anterior. Se a string que _executa_ não for o comando que a invocação _representa_ (por exemplo, encapsula um `source <snapshot> && eval '<cmd>'` montado), passe também `commandText: '<cmd>'`: é contra isto que os padrões de comando de `ignoreViolations` são comparados e é o que cada violação reporta como o seu `command`. Um `commandId` que passe a `wrapWithSandbox` tem de ser a mesma string não vazia que depois passa a `annotateStderrWithSandboxFailures` / `getViolationsForCommand`; um vazio é tratado como se não houvesse `commandId` de todo, pelo que a chave é o comando.

Apenas a chave é cortada para 100 caracteres. A partir da v0.0.76, o `command` reportado — e o texto contra o qual os padrões de comando de `ignoreViolations` são comparados — é o comando completo para uma invocação encapsulada sem um `commandId`, e não os seus primeiros 100 caracteres; um padrão pode, portanto, apenas suprimir mais do que antes, nunca menos. Uma chave de atribuição que nenhuma invocação deste processo registou (os transportadores são graváveis a partir do interior da sandbox) é reportada sanitizada e cortada para esse mesmo comprimento de chave.

```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,
)
```

**Perguntar sobre um host que nenhuma regra decide (o callback de consulta).** O segundo argumento de `SandboxManager.initialize` é um `SandboxAskCallback` opcional. Ele é consultado sobre um destino que nem `network.deniedDomains`, nem `network.allowedDomains`, nem uma lista de permissões por comando (próxima seção) decidiram, e nunca é consultado sob `network.strictAllowlist`. Sem um callback, tal destino é negado. O callback resolve para um dos seguintes:

- `true` - permite a conexão. Apenas o valor `true` permite.
- `false` - nega-a. A linha de violação reporta o motivo genérico `user denied`.
- `{ allow: false, reason: '...' }` - nega-a, e reporta `reason` na linha de violação em vez do texto genérico, para que quem lê o bloco `<sandbox_violations>` (incluindo um modelo) saiba por quê e o que fazer em vez disso. O cliente em sandbox também o lê, como a frase de status do `403` que responde ao seu CONNECT.

Qualquer outra resposta nega, seja ela truthy ou não, e reporta o motivo genérico. Isso inclui um objeto que carrega um `reason` sem dizer `allow: false`, como `{ allow: true, reason: '...' }`: seu motivo não é reportado.

O motivo é sanitizado antes de ser armazenado, da mesma forma que o restante de uma linha de violação. Cada sequência de caracteres de controle (incluindo quebras de linha e tabulações) ou de caracteres invisíveis (caracteres de largura zero, incluindo o joiner, e controles bidi) torna-se um espaço; `<` e `>` são removidos, então `re-run with <host> listed` é armazenado como `re-run with host listed`; as extremidades são aparadas. O resultado é cortado em 500 caracteres, contados como unidades de código UTF-16 da forma como `String.prototype.length` os conta. Um motivo sem nada restante após isso recai para `user denied`. Escreva-o como uma linha de texto simples.

**Mudança de comportamento na primeira versão após 0.0.79:** o filtro costumava permitir em qualquer resposta truthy, então um callback que resolvia para um valor truthy diferente de `true` (`1`, uma string, qualquer objeto) permitia a conexão. Agora ele nega. Pelo mesmo motivo, `{ allow: false, reason }` retornado a uma versão mais antiga seria lido lá como uma permissão, porque um objeto é truthy. `SandboxManager.askCallbackDenyReason` é `true` em uma versão que entende o objeto: verifique-o antes de retornar um, e negue com um `false` simples onde ele estiver ausente.

```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 permissões de rede por comando (`registerCommandNetworkLists`).** Uma invocação pode carregar uma lista de permissões própria, além da configurada, durante todo o seu tempo de execução:

```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
```

As entradas usam a gramática e o matcher de `network.allowedDomains` e recebem a mesma validação. `registerCommandNetworkLists` lança erro em uma entrada inválida e em um `commandId` com menos de 22 caracteres (um surrogate não pareado não conta). Registrar um id novamente substitui sua lista; `unregisterCommandNetworkLists` é uma no-op para um id que não possui nenhuma; `reset()` remove todos os registros.

A ordem de avaliação para uma conexão é:

1. uma correspondência em `network.deniedDomains` nega;
2. uma correspondência em `network.allowedDomains` permite;
3. `network.strictAllowlist` nega;
4. uma correspondência na lista registrada para o id que a conexão apresenta permite;
5. o callback de ask decide se houver um, e caso contrário a conexão é negada.

Assim, uma entrada por comando nunca sobrepõe uma entrada configurada em `deniedDomains` e é totalmente ignorada sob `strictAllowlist`. Ela também nunca entra em `network.*`: `getConfig()` e `getNetworkRestrictionConfig()` não a exibem, e o escopo padrão `injectHosts` de uma credencial mascarada, que é `network.allowedDomains`, não cresce. Um host permitido dessa forma ainda passa pela verificação de endereço resolvido quando é discado, e um literal de IP em uma lista por comando não adiciona nenhuma isenção ali.

O que o id precisa ser, e o que este recurso não é: o proxy descobre a qual invocação uma conexão pertence a partir do nome de usuário do proxy, e o nome de usuário é apresentado pelo cliente dentro do sandbox. O id é, portanto, a **única** coisa que vincula uma conexão a uma lista de permissões. Ele **deve** ser impossível de adivinhar: pelo menos 128 bits de aleatoriedade, nunca um contador, um timestamp ou qualquer coisa derivada do comando. Um processo em sandbox que apresenta o id de outra invocação ativa recebe as permissões dessa invocação, então isto é atribuição, não uma fronteira entre comandos concorrentes de uma mesma sessão. Registre logo antes de gerar o comando encapsulado, e cancele o registro quando o processo filho sair ou nunca tiver iniciado: um registro que sobrevive ao seu comando amplia a janela na qual seu id vale a pena ser apresentado. Como em toda chave de atribuição, apenas os primeiros 100 caracteres de um id participam. Mantenha os ids em ASCII: uma lista sob um id não-ASCII cuja forma codificada não cabe no nome de usuário do proxy (255 bytes) é registrada e nunca se aplica.

Nenhuma lista se aplica enquanto `network.httpProxyPort` nomear um proxy externo: o wrap não fornece nome de usuário a esse proxy, então nenhuma conexão carrega um id. `registerCommandNetworkLists` ainda tem sucesso (e informa isso em uma linha sob `SRT_DEBUG`), e toda conexão é decidida como se nenhuma lista existisse.

#### Exportações disponíveis

```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'
```

## Configuração

### Localização do Arquivo de Configurações

Por padrão, o runtime do sandbox procura a configuração em `~/.srt-settings.json`. Você pode especificar um caminho personalizado usando a flag `--settings`:

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

### Exemplo de Configuração 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
}
```

### Opções de Configuração

#### Configuração de Rede

Usa um **padrão allow-only** — todo acesso à rede é negado por padrão.

- `network.allowedDomains` - Array de domínios permitidos (suporta wildcards como `*.example.com`). Array vazio = sem acesso à rede. Um sufixo opcional `:port` (`api.example.com:443`, `*.example.com:8443`) restringe uma entrada a essa porta de destino; entradas sem porta correspondem a qualquer porta.
  - Literais IPv6 devem estar entre colchetes, no estilo RFC 3986: `[::1]`, `[2001:db8::1]:443`. Uma entrada com múltiplos dois-pontos sem colchetes é rejeitada como ambígua (`2001:db8::1:443` é, por si só, um endereço válido).
- `network.deniedDomains` - Array de domínios negados (verificado primeiro, tem precedência sobre allowedDomains). Mesmo sufixo `:port`, e um `*` isolado (ou `*:22`) é aceito para negar tudo.
- `network.deniedDomainReasons` - Mapa opcional de uma entrada de `deniedDomains` (correspondida por string exata) para um motivo voltado ao modelo que aparece na linha `<sandbox_violations>` quando essa entrada nega uma conexão — diga o que está bloqueado e a alternativa sancionada (por exemplo, `{"github.com:22": "SSH pushes to GitHub are blocked; use an https:// remote"}`). Entradas sem motivo reportam um genérico. Para destinos SSH (porta 22), o motivo também é entregue in-band: um cliente SSH tunelado através de um ProxyCommand SOCKS sem autenticação (por exemplo, BSD `nc -X 5`) recebe um disconnect SSH pré-troca-de-chaves cuja descrição é o motivo, que o OpenSSH imprime literalmente — mantenha tais motivos com menos de ~400 caracteres ASCII, com o imperativo primeiro, já que o OpenSSH trunca e escapa caracteres não-ASCII. Um cliente que de fato autentica, como o `GIT_SSH_COMMAND` que o srt injeta, recebe o motivo em qualquer porta como a frase de status do `403` que responde ao seu CONNECT, que é o que esse comando, e muitos clientes HTTP, imprimem. Lá ele é limpo e cortado como na linha de violação, e todo caractere não-ASCII se torna `?`, já que os clientes discordam sobre como ler um em uma linha de status.
- `network.allowLocalBinding` - Permite que comandos em sandbox usem portas locais diretamente (booleano, padrão: false). macOS: bind e accept em qualquer porta local, e conectar a `localhost` em qualquer porta. Windows: conectar a endereços de loopback em qualquer porta TCP ou UDP; faz parte da instalação para toda a máquina, veja [Local servers on Windows](#local-servers-on-windows). Linux: ignorado — o sandbox tem seu próprio network namespace, cujo loopback é sempre utilizável e não é o do host.

**Verificação de endereço resolvido.** As listas de permitir/negar correspondem por _nome_, mas quem controla o DNS de um nome permitido (ou de qualquer rótulo sob um wildcard permitido) controla para o que ele resolve. Assim, antes de discar diretamente para um **hostname** permitido, o proxy o resolve uma vez, descarta qualquer endereço em um conjunto negado e conecta a um endereço sobrevivente (o endereço que passou na verificação é o que é discado — não há segunda consulta). Se nada sobreviver, a conexão é recusada como qualquer outra negação de política: HTTP/CONNECT recebem `403` (`X-Proxy-Error: blocked-by-sandbox-runtime`, o motivo no corpo e, para um CONNECT, como a frase de status), SOCKS recebe "connection not allowed by ruleset", e uma linha `deny network-outbound host:port (resolved to a loopback address)` — nomeando a classe do endereço (loopback, link-local, deste host, metadados de nuvem, na lista de negação, listado, …), não o endereço em si, que apenas o log de depuração carrega — é registrada no armazenamento de violações.

O conjunto negado é: loopback (`127.0.0.0/8`, `::1`), não especificado (`0.0.0.0/8`, `::`), link-local (`169.254.0.0/16`, `fe80::/10`), multicast (`224.0.0.0/4`, `ff00::/8`), broadcast, os endpoints de metadados de instância em nuvem / plataforma que ficam fora do 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`), todos os endereços atualmente atribuídos a uma das interfaces de rede deste próprio host (um serviço vinculado a `0.0.0.0` responde no endereço LAN ou global exatamente como responde no loopback), todos os literais IP listados em `deniedDomains` (respeitando seu `:port` se houver) e qualquer coisa em `deniedResolvedAddresses`. Entradas IPv4 também correspondem às formas IPv6 que carregam um endereço IPv4 — endereços IPv4-mapeados, IPv4-compatíveis e IPv4-traduzidos, o prefixo bem conhecido NAT64 (`64:ff9b::/96`) e 6to4 (`2002::/16`) são julgados pelo endereço IPv4 que incorporam. O prefixo NAT64 de uso local `64:ff9b:1::/48` e prefixos específicos de rede não são decodificados — seu layout (a RFC 6052 permite o IPv4 em várias posições) não pode ser reconhecido apenas pelo endereço; em tal rede, liste as traduções do prefixo para os intervalos que você nega (por exemplo, `<prefix>::a00:0/104` para `10.0.0.0/8`). Endereços que alcançam este host sem estarem atribuídos a ele — o endereço público 1:1-NAT de uma instância em nuvem, um port-forward de roteador, um alias de host-gateway de contêiner ou VM — não são cobertos automaticamente; liste-os em `deniedResolvedAddresses`.

---

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