Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
sandbox-runtime — Uno strumento di sandboxing leggero per applicare restrizioni su filesystem e rete a processi arbitrari a livello di sistema operativo, senza richiedere un container. | Kitploit
Strumenti/GitHubGitHub/anthropic-experimental/sandbox-runtime
Strumenti DifensiviSicurezza dei ContenitoriAnalisi Dinamica (Sandboxing)Audit di ConfigurazioneVirtualizzazione per la SicurezzaSicurezza di ReteRisposta agli Incidenti
GitHub

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
anthropic-experimental/sandbox-runtime

sandbox-runtime

Uno strumento di sandboxing leggero per applicare restrizioni su filesystem e rete a processi arbitrari a livello di sistema operativo, senza richiedere un container.

Vedi Repository
4.9k3991501 giorno faRevisionato da Kitploit
Condividi
# Anthropic Sandbox Runtime (srt)

Uno strumento di sandboxing leggero per applicare restrizioni sul filesystem e sulla rete a processi arbitrari a livello di sistema operativo, senza richiedere un container.

`srt` utilizza le primitive native di sandboxing del sistema operativo (`sandbox-exec` su macOS, `bubblewrap` su Linux) e il filtraggio di rete basato su proxy. Può essere usato per confinare in sandbox il comportamento di agenti, server MCP locali, comandi bash e processi arbitrari.

> **Anteprima di ricerca Beta**
>
> Il Sandbox Runtime è un'anteprima di ricerca sviluppata per [Claude Code](https://www.claude.com/product/claude-code) per consentire agenti AI più sicuri. Viene resa disponibile come anteprima open source iniziale per aiutare l'ecosistema più ampio a costruire sistemi agentici più sicuri. Trattandosi di un'anteprima di ricerca iniziale, le API e i formati di configurazione possono evolvere. Accogliamo con favore feedback e contributi per rendere gli agenti AI più sicuri per impostazione predefinita!

## Installazione

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

## Utilizzo di base

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

## Panoramica

Questo pacchetto fornisce un'implementazione sandbox autonoma che può essere utilizzata sia come strumento CLI che come libreria. È progettata con una filosofia **secure-by-default** (sicura per impostazione predefinita) adattata ai casi d'uso comuni degli sviluppatori: i processi partono con accesso minimo e si aprono esplicitamente solo le eccezioni necessarie.

**Funzionalità principali:**

- **Restrizioni di rete**: controlla quali host/domini possono essere accessibili tramite HTTP/HTTPS e altri protocolli
- **Restrizioni del filesystem**: controlla quali file/directory possono essere letti/scritti
- **Restrizioni dei socket Unix**: controlla l'accesso ai socket IPC locali
- **Monitoraggio delle violazioni**: su macOS, accede all'archivio dei log delle violazioni della sandbox di sistema per avvisi in tempo reale

### Caso d'uso di esempio: sandboxing dei server MCP

Un caso d'uso importante è il sandboxing dei server Model Context Protocol (MCP) per limitarne le capacità. Ad esempio, per applicare il sandboxing al server MCP del filesystem:

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

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

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

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

Poi configura le restrizioni in `~/.srt-settings.json`:

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

Ora il server MCP sarà bloccato dalla scrittura nel percorso negato:

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

## Come funziona

La sandbox utilizza primitive a livello di sistema operativo per applicare restrizioni che si estendono all'intero albero dei processi:

- **macOS**: utilizza `sandbox-exec` con [profili Seatbelt](https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf) generati dinamicamente
- **Linux**: utilizza [bubblewrap](https://github.com/containers/bubblewrap) per la containerizzazione con isolamento dello spazio dei nomi di rete
- **Windows**: esegue il processo in sandbox sotto un account utente locale dedicato `srt-sandbox`, con una barriera in uscita basata su [Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/windows-filtering-platform-start-page) associata al SID di tale account, un token con restrizioni di scrittura e ACE espliciti sull'albero di lavoro

0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305

### Modello di isolamento duale

Sia l'isolamento del filesystem che quello della rete sono necessari per una sandbox efficace. Senza l'isolamento dei file, un processo compromesso potrebbe esfiltrare chiavi SSH o altri file sensibili. Senza l'isolamento della rete, un processo potrebbe sfuggire alla sandbox e ottenere accesso di rete senza restrizioni.

**Isolamento del filesystem** applica restrizioni di lettura e scrittura:

- **Lettura** (schema nega-poi-consenti): per impostazione predefinita, l'accesso in lettura è consentito ovunque. È possibile negare ampie regioni (ad es. `/Users`) e poi ri-consentire percorsi specifici al loro interno (ad es. `.`). `allowRead` ha la precedenza su `denyRead` — l'opposto della scrittura, dove `denyWrite` ha la precedenza su `allowWrite`. Una voce `denyRead` più specifica della regione `allowRead` in cui ricade (ad es. `denyRead: ["**/.env"]` o `["./secrets"]` con `allowRead: ["."]`) rimane comunque negata.
- **Scrittura** (schema solo-consenti): per impostazione predefinita, l'accesso in scrittura è negato ovunque. È necessario consentire esplicitamente i percorsi (ad es. `.`, `/tmp`). Una lista di autorizzazioni vuota significa nessun accesso in scrittura.

**Isolamento della rete** (schema solo-consenti): per impostazione predefinita, tutto l'accesso alla rete è negato. È necessario consentire esplicitamente i domini. Una lista allowedDomains vuota significa nessun accesso alla rete. Il traffico di rete viene instradato attraverso server proxy in esecuzione sull'host:

- **Linux**: le richieste vengono instradate tramite il filesystem su un socket di dominio Unix. Lo spazio dei nomi di rete del processo in sandbox viene rimosso completamente, quindi tutto il traffico di rete deve passare attraverso i proxy in esecuzione sull'host (in ascolto su socket Unix montati tramite bind nella sandbox)

- **macOS**: il profilo Seatbelt consente la comunicazione solo verso una porta specifica di localhost. I proxy sono in ascolto su questa porta, creando un canale controllato per tutto l'accesso alla rete

- **Windows**: un insieme di filtri WFP a livello di macchina blocca le connessioni in uscita effettuate da processi in esecuzione con l'account `srt-sandbox`, eccetto il loopback verso l'intervallo di porte del proxy. I proxy sono in ascolto all'interno di tale intervallo, creando un canale controllato per tutto l'accesso alla rete. I filtri non seguono un processo in sandbox che applica un token diverso a un thread prima di creare un socket, né il traffico che un servizio di sistema trasporta per suo conto; vedere le [limitazioni note](#known-limitations) di Windows

Sia il traffico HTTP/HTTPS (tramite proxy HTTP) che altro traffico TCP (tramite proxy SOCKS5) sono mediati da questi proxy, che applicano le liste di domini consentiti e negati.

Per maggiori dettagli sul sandboxing in Claude Code, vedere:

- [Documentazione sul sandboxing di Claude Code](https://docs.claude.com/en/docs/claude-code/sandboxing)
- [Oltre i prompt di autorizzazione: rendere Claude Code più sicuro e autonomo](https://www.anthropic.com/engineering/claude-code-sandboxing)

## Architettura

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

## Utilizzo

### Come strumento CLI

Il comando `srt` (Anthropic Sandbox Runtime) avvolge qualsiasi comando con confini di sicurezza:

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

Il file delle impostazioni è opzionale — senza alcun file in `~/.srt-settings.json`, `srt` viene eseguito con i valori predefiniti integrati: nessun accesso alla rete, nessuna scrittura al di fuori dei percorsi di scrittura predefiniti e letture senza restrizioni. Un file delle impostazioni che _è_ presente ma è vuoto, non può essere letto o non viene validato è un errore: `srt` lo segnala ed esce invece di ricadere su quei valori predefiniti, che rappresentano una configurazione diversa anziché una più debole — ricadere su di essi eliminerebbe le regole `denyRead`, `allowRead` e sulle credenziali del file, insieme a tutto il resto che specificava. Lo stesso vale per un file indicato con `--settings`, che deve anch'esso esistere.

#### Aggiornare la configurazione mentre il comando è in esecuzione: `--control-fd`

`--control-fd <fd>` legge gli aggiornamenti della configurazione da un descrittore che il chiamante ha già aperto, un oggetto JSON per riga con la stessa struttura del file delle impostazioni. Ogni riga sostituisce l'intera configurazione ed è validata rispetto allo stesso schema, quindi una riga è una configurazione completa anziché una patch: `network` e `filesystem` sono obbligatori, e una chiave omessa nella riga torna al suo valore predefinito.

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

Cosa cambia una riga accettata una volta che il comando è in esecuzione:

- Gli elenchi di rete — `network.allowedDomains`, `deniedDomains` (con
  `deniedDomainReasons`) e `deniedResolvedAddresses` — hanno effetto alla
  connessione successiva, su ogni piattaforma: il proxy li consulta per ogni
  richiesta, e il controllo degli indirizzi risolti viene ricostruito dalla
  stessa riga. Lo stesso vale per
  `network.mitmProxy` e `network.tlsTerminate.excludeDomains`, che legge
  anch'essi per ogni richiesta.
- `credentials.sigv4` ha effetto alla richiesta successiva, a condizione che srt
  sia stato avviato con un blocco `credentials`: l'hook di firma viene installato
  solo in quel caso, e legge le policy per ogni richiesta anziché catturarle.
- Nient'altro cambia. Le regole del filesystem sono già nel profilo seatbelt,
  negli argv di bubblewrap o nelle ACE di Windows, le maschere delle credenziali
  sono state costruite quando il comando è stato incapsulato, e i server proxy
  in esecuzione hanno catturato `network.parentProxy`, e se TLS viene terminato
  del tutto, all'avvio.
- Su Windows, srt rileva una riga il cui insieme di accesso ai file (`filesystem.*`
  insieme a `credentials.files`) differisce da quello applicato all'avvio, e lo
  segnala solo con `SRT_DEBUG`: la concessione ACL è a livello di sessione, quindi
  l'insieme applicato all'avvio resta in vigore. Il resto della riga viene
  applicato come sopra.

Come srt legge il canale, e cosa rifiuta:

- Il descrittore deve essere un intero **3 o superiore** e leggibile — `0`-`2`
  sono gli stream standard. srt esce con un errore anziché eseguire il
  comando quando non riesce a leggere il descrittore che gli è stato fornito,
  così un canale morto non passa mai per uno vivo. Un canale che muore prima di
  aver consegnato un singolo aggiornamento porta giù con sé il comando; uno che
  muore dopo lo segnala e lascia il comando in esecuzione con la configurazione
  applicata per ultima.
- Una riga che non è una configurazione valida viene segnalata su stderr e
  scartata; la configurazione precedente resta in vigore. La riga stessa finisce
  nel log di debug anziché nel terminale, e una riga vuota viene ignorata
  silenziosamente.
- srt inizia a leggere solo quando la sandbox è attiva, quindi un aggiornamento
  scritto prima di allora attende nel canale anziché andare perso — e non può
  essere sovrascritto dalla configurazione con cui la sandbox si avvia. Tale riga
  può essere letta mentre il comando è ancora in fase di incapsulamento, ed è
  quindi la configurazione con cui viene incapsulato, regole del filesystem
  incluse. Se venga letta così presto dipende da quanto dura l'incapsulamento
  (su Linux, un glob di negazione su un albero ampio è sufficiente), quindi una
  regola sotto cui il comando deve partire va nel file delle impostazioni.
- srt **esce con il comando incapsulato** e non attende che lo scrittore
  chiuda il descrittore. Anche la fine dell'input non è un errore: il
  comando continua a essere eseguito con la configurazione applicata per ultima.
- Fornisci a srt un **estremo dedicato e di sola lettura**. srt mette una pipe o
  un socket in modalità non bloccante, e quel flag risiede sulla descrizione del
  file aperto, quindi qualsiasi altra cosa che detenga la stessa descrizione — un
  `exec 3<fifo` di una shell, un `pass_fds` di un descrittore che il processo
  padre continua a usare — riceve `EAGAIN` dalle proprie letture bloccanti da
  quel momento in poi.
- Su macOS e Linux il comando in sandbox non riceve il descrittore: srt
  punta quello slot a `/dev/null` per il comando, così nulla all'interno della
  sandbox può leggere gli aggiornamenti o scrivere una configurazione propria. Su
  Windows il comando viene avviato con i soli tre stream standard, quindi il
  descrittore di controllo non è tra i descrittori che gli vengono passati.

### Come proxy autonomo con un decisore esterno: `srt proxy`

`srt proxy` (o l'eseguibile monofile `srt-proxy` creato da `bun run build:srt-proxy`) esegue solo il proxy HTTP di SRT, senza alcun processo figlio in sandbox, per un host che esegue il carico di lavoro altrove. Accetta su un socket in ascolto che l'host gli fornisce, termina ogni CONNECT nel processo, e inoltra una richiesta solo quando un processo decisore separato, raggiunto tramite un altro descrittore ereditato, lo consente. Vedi [docs/srt-proxy.md](https://github.com/anthropic-experimental/sandbox-runtime/blob/main/docs/srt-proxy.md) per la riga di comando, il protocollo del decisore e il modello di sicurezza.

### Come libreria

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

**Attribuzione delle violazioni (`commandId` / `commandText`).** Le violazioni osservate durante l'esecuzione di un comando incapsulato (righe di log di seatbelt, eventi seccomp, blocchi del proxy) vengono memorizzate sotto una chiave di attribuzione, e `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` le cercano tramite quella stessa chiave. Per impostazione predefinita la chiave è la stringa incapsulata stessa. Passa un `commandId` opaco per singola invocazione (ad es. un id di tool-use) per usare quello come chiave — consigliato: le chiavi vengono confrontate sui loro primi 100 caratteri, quindi comandi lunghi che condividono un prefisso verrebbero altrimenti attribuiti in modo incrociato, e una riesecuzione dello stesso testo erediterebbe gli eventi dell'esecuzione precedente. Se la stringa che _esegui_ non è il comando che l'invocazione _rappresenta_ (ad es. incapsuli un `source <snapshot> && eval '<cmd>'` assemblato), passa anche `commandText: '<cmd>'`: è ciò su cui vengono confrontati i pattern dei comandi di `ignoreViolations` e ciò che ogni violazione riporta come proprio `command`. Un `commandId` che passi a `wrapWithSandbox` deve essere la stessa stringa non vuota che poi passi a `annotateStderrWithSandboxFailures` / `getViolationsForCommand`; uno vuoto è trattato come nessun `commandId`, quindi la chiave è il comando.

Solo la chiave viene troncata a 100 caratteri. A partire dalla v0.0.76 il `command` riportato — e il testo su cui vengono confrontati i pattern dei comandi di `ignoreViolations` — è il comando intero per un'invocazione incapsulata senza un `commandId`, non i suoi primi 100 caratteri; un pattern può quindi solo sopprimere più di prima, mai meno. Una chiave di attribuzione che nessuna invocazione di questo processo ha registrato (i carrier sono scrivibili dall'interno della sandbox) viene riportata sanitizzata e troncata a quella stessa lunghezza della chiave.

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

**Richiesta su un host che nessuna regola decide (la callback ask).** Il secondo argomento di `SandboxManager.initialize` è un `SandboxAskCallback` opzionale. Viene interrogato su una destinazione che né `network.deniedDomains`, né `network.allowedDomains`, né una allow list per comando (sezione successiva) hanno deciso, e non viene mai interrogato con `network.strictAllowlist`. Senza una callback tale destinazione viene negata. La callback si risolve in uno dei seguenti valori:

- `true` - consente la connessione. Solo il valore `true` consente.
- `false` - la nega. La riga di violazione riporta il motivo generico `user denied`.
- `{ allow: false, reason: '...' }` - la nega e riporta `reason` nella riga di violazione al posto del testo generico, così che chiunque legga il blocco `<sandbox_violations>` (modello incluso) apprenda il perché e cosa fare invece. Anche il client in sandbox lo legge, come frase di stato del `403` che risponde al suo CONNECT.

Qualsiasi altra risposta nega, che sia truthy o meno, e riporta il motivo generico. Ciò include un oggetto che porta un `reason` senza dichiarare `allow: false`, come `{ allow: true, reason: '...' }`: il suo motivo non viene riportato.

Il motivo viene sanitizzato prima di essere memorizzato, come il resto di una riga di violazione. Ogni sequenza di caratteri di controllo (interruzioni di riga e tabulazioni incluse) o di caratteri invisibili (caratteri a larghezza zero, il joiner tra questi, e i controlli bidi) diventa uno spazio; `<` e `>` vengono rimossi, quindi `re-run with <host> listed` viene memorizzato come `re-run with host listed`; le estremità vengono rifilate. Il risultato viene tagliato a 500 caratteri, contati come unità di codice UTF-16 nel modo in cui le conta `String.prototype.length`. Un motivo che non ha più nulla dopo ciò ricade su `user denied`. Scrivilo come una singola riga di testo semplice.

**Cambiamento di comportamento nella prima release dopo la 0.0.79:** il filtro consentiva su qualsiasi risposta truthy, quindi una callback che si risolveva in un valore truthy diverso da `true` (`1`, una stringa, qualsiasi oggetto) consentiva la connessione. Ora la nega. Per lo stesso motivo, `{ allow: false, reason }` restituito a una release più vecchia verrebbe letto lì come un consenso, poiché un oggetto è truthy. `SandboxManager.askCallbackDenyReason` è `true` su una release che comprende l'oggetto: controllalo prima di restituirne uno, e nega con un semplice `false` dove è assente.

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

**Allow list di rete per singolo comando (`registerCommandNetworkLists`).** Una singola invocazione può portare con sé una propria allow list, in aggiunta a quella configurata, per tutta la durata della sua esecuzione:

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

Le voci usano la grammatica e il matcher di `network.allowedDomains` e ricevono la stessa validazione. `registerCommandNetworkLists` genera un errore su una voce non valida e su un `commandId` più corto di 22 caratteri (un surrogato non accoppiato non conta). Registrare di nuovo un id sostituisce la sua lista; `unregisterCommandNetworkLists` è un no-op per un id che non ne ha; `reset()` rimuove ogni registrazione.

L'ordine di valutazione per una connessione è:

1. una corrispondenza in `network.deniedDomains` nega;
2. una corrispondenza in `network.allowedDomains` consente;
3. `network.strictAllowlist` nega;
4. una corrispondenza nella lista registrata per l'id presentato dalla connessione consente;
5. il callback ask decide se presente, altrimenti la connessione viene negata.

Quindi una voce per-comando non sovrascrive mai una voce configurata in `deniedDomains`, ed è del tutto ignorata sotto `strictAllowlist`. Non entra mai nemmeno in `network.*`: `getConfig()` e `getNetworkRestrictionConfig()` non la mostrano, e l'ambito predefinito `injectHosts` di una credenziale mascherata, che è `network.allowedDomains`, non si amplia. Un host consentito in questo modo passa comunque il controllo dell'indirizzo risolto quando viene contattato, e un IP letterale in una lista per-comando non aggiunge alcuna esenzione in tal senso.

Cosa deve essere l'id, e cosa questa funzionalità non è: il proxy apprende a quale invocazione appartiene una connessione dal nome utente del proxy, e il nome utente è presentato dal client all'interno della sandbox. L'id è quindi la **sola** cosa che lega una connessione a una lista di autorizzazione. **Deve** essere non indovinabile: almeno 128 bit di casualità, mai un contatore, un timestamp o qualsiasi cosa derivata dal comando. Un processo in sandbox che presenta l'id di un'altra invocazione attiva ottiene le autorizzazioni di quell'invocazione, quindi questa è attribuzione, non un confine tra comandi concorrenti di una stessa sessione. Registra subito prima di avviare il comando incapsulato, e annulla la registrazione quando il processo figlio termina o non è mai partito: una registrazione che sopravvive al proprio comando amplia la finestra in cui il suo id vale la pena di essere presentato. Come per ogni chiave di attribuzione, solo i primi 100 caratteri di un id prendono parte. Mantieni gli id ASCII: una lista sotto un id non ASCII la cui forma codificata non entra nel nome utente del proxy (255 byte) viene registrata e non si applica mai.

Nessuna lista si applica mentre `network.httpProxyPort` indica un proxy esterno: il wrap non fornisce alcun nome utente a quel proxy, quindi nessuna connessione porta un id. `registerCommandNetworkLists` ha comunque successo (e lo segnala in una riga sotto `SRT_DEBUG`), e ogni connessione viene decisa come se nessuna lista esistesse.

#### Export disponibili

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

## Configurazione

### Posizione del file delle impostazioni

Per impostazione predefinita, il runtime della sandbox cerca la configurazione in `~/.srt-settings.json`. È possibile specificare un percorso personalizzato utilizzando il flag `--settings`:

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

### Esempio di configurazione 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
}
```

### Opzioni di configurazione

#### Configurazione di rete

Utilizza un **pattern allow-only** - tutto l'accesso alla rete è negato per impostazione predefinita.

- `network.allowedDomains` - Array di domini consentiti (supporta wildcard come `*.example.com`). Array vuoto = nessun accesso alla rete. Un suffisso opzionale `:port` (`api.example.com:443`, `*.example.com:8443`) limita una voce a quella porta di destinazione; le voci senza porta corrispondono a qualsiasi porta.
  - I letterali IPv6 devono essere racchiusi tra parentesi quadre, in stile RFC 3986: `[::1]`, `[2001:db8::1]:443`. Una voce con più due punti non racchiusa tra parentesi quadre viene rifiutata come ambigua (`2001:db8::1:443` è di per sé un indirizzo valido).
- `network.deniedDomains` - Array di domini negati (verificati per primi, hanno precedenza su allowedDomains). Stesso suffisso `:port`, e un `*` nudo (o `*:22`) è accettato per negare tutto.
- `network.deniedDomainReasons` - Mappa opzionale da una voce di `deniedDomains` (corrispondenza per stringa esatta) a un motivo rivolto al modello che appare nella riga `<sandbox_violations>` quando quella voce nega una connessione — indica cosa è bloccato e l'alternativa consentita (ad es. `{"github.com:22": "SSH pushes to GitHub are blocked; use an https:// remote"}`). Le voci senza motivo ne riportano uno generico. Per le destinazioni SSH (porta 22), il motivo viene anche consegnato in-band: un client SSH incanalato attraverso un ProxyCommand SOCKS senza autenticazione (ad es. BSD `nc -X 5`) riceve una disconnessione SSH pre-scambio-di-chiavi la cui descrizione è il motivo, che OpenSSH stampa testualmente — mantieni tali motivi sotto ~400 caratteri ASCII, con l'imperativo all'inizio, poiché OpenSSH tronca ed esegue l'escape dei caratteri non ASCII. Un client che effettivamente si autentica, come fa il `GIT_SSH_COMMAND` che srt inietta, riceve il motivo su qualsiasi porta come frase di stato del `403` che risponde al suo CONNECT, che è ciò che quel comando, e molti client HTTP, stampano. Lì viene ripulito e troncato come nella riga di violazione, e ogni carattere non ASCII diventa `?`, poiché i client non concordano su come leggerlo in una riga di stato.
- `network.allowLocalBinding` - Consente ai comandi in sandbox di usare direttamente le porte locali (booleano, predefinito: false). macOS: esegue il bind e accetta su qualsiasi porta locale, e si connette a `localhost` su qualsiasi porta. Windows: si connette agli indirizzi di loopback su qualsiasi porta TCP o UDP; fa parte dell'installazione a livello di macchina, vedi [Server locali su Windows](#local-servers-on-windows). Linux: ignorato — la sandbox ha il proprio network namespace, il cui loopback è sempre utilizzabile e non è quello dell'host.

**Verifica dell'indirizzo risolto.** Le liste allow/deny corrispondono per _nome_, ma chi controlla il DNS di un nome consentito (o qualsiasi etichetta sotto una wildcard consentita) controlla ciò a cui risolve. Quindi, prima di contattare direttamente un **hostname** consentito, il proxy lo risolve una volta, scarta qualsiasi indirizzo in un insieme negato e si connette a un indirizzo sopravvissuto (l'indirizzo che ha superato la verifica è quello contattato — non c'è una seconda risoluzione). Se non sopravvive nulla, la connessione viene rifiutata come qualsiasi altra negazione di policy: HTTP/CONNECT ricevono `403` (`X-Proxy-Error: blocked-by-sandbox-runtime`, il motivo nel corpo e, per un CONNECT, come frase di stato), SOCKS riceve "connection not allowed by ruleset", e una riga `deny network-outbound host:port (resolved to a loopback address)` — che nomina la classe di indirizzo (loopback, link-local, di questo host, metadata cloud, in deny-list, in lista, …), non l'indirizzo stesso, che solo il log di debug riporta — viene registrata nell'archivio delle violazioni.

L'insieme degli indirizzi negati è: loopback (`127.0.0.0/8`, `::1`), non specificato (`0.0.0.0/8`, `::`), link-local (`169.254.0.0/16`, `fe80::/10`), multicast (`224.0.0.0/4`, `ff00::/8`), broadcast, gli endpoint di metadati dell'istanza cloud / della piattaforma che risiedono al di fuori del 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`), ogni indirizzo attualmente assegnato a una delle interfacce di rete di questo host (un servizio in ascolto su `0.0.0.0` risponde sull'indirizzo LAN o globale esattamente come fa sul loopback), ogni letterale IP elencato in `deniedDomains` (rispettando la sua `:port` se ne ha una) e qualsiasi cosa presente in `deniedResolvedAddresses`. Le voci IPv4 corrispondono anche alle forme IPv6 che trasportano un indirizzo IPv4 — gli indirizzi IPv4-mapped, IPv4-compatible e IPv4-translated, il prefisso well-known NAT64 (`64:ff9b::/96`) e 6to4 (`2002::/16`) vengono giudicati in base all'indirizzo IPv4 che incorporano. Il prefisso NAT64 local-use `64:ff9b:1::/48` e i prefissi specifici della rete non vengono decodificati — la loro disposizione (RFC 6052 consente l'IPv4 in diverse posizioni) non può essere riconosciuta dal solo indirizzo; su una rete di questo tipo, elenca le traduzioni del prefisso per gli intervalli che vuoi negare (ad es. `<prefix>::a00:0/104` per `10.0.0.0/8`). Gli indirizzi che raggiungono questo host senza essergli assegnati — l'indirizzo pubblico 1:1-NAT di un'istanza cloud, un port-forward del router, un alias host-gateway di un container o di una VM — non sono coperti automaticamente; elencali in `deniedResolvedAddresses`.

---

[Read more](https://github.com/anthropic-experimental/sandbox-runtime)
Scarica lo strumento