Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
sandbox-runtime — Un outil de sandboxing léger pour appliquer des restrictions de système de fichiers et de réseau à des processus arbitraires au niveau du système d'exploitation, sans nécessiter de conteneur. | Kitploit
Outils/GitHubGitHub/anthropic-experimental/sandbox-runtime
Outils DéfensifsSécurité des ConteneursAnalyse Dynamique (Sandboxing)Audit de ConfigurationVirtualisation de SécuritéSécurité RéseauRéponse aux Incidents
GitHub

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
anthropic-experimental/sandbox-runtime

sandbox-runtime

Un outil de sandboxing léger pour appliquer des restrictions de système de fichiers et de réseau à des processus arbitraires au niveau du système d'exploitation, sans nécessiter de conteneur.

Voir le dépôt
4.9k399151il y a 2 joursVérifié par Kitploit
Partager
# Anthropic Sandbox Runtime (srt)

Un outil de sandboxing léger pour appliquer des restrictions de système de fichiers et de réseau à des processus arbitraires au niveau du système d'exploitation, sans nécessiter de conteneur.

`srt` utilise les primitives natives de sandboxing du système d'exploitation (`sandbox-exec` sur macOS, `bubblewrap` sur Linux) et un filtrage réseau basé sur un proxy. Il peut être utilisé pour sandboxer le comportement d'agents, de serveurs MCP locaux, de commandes bash et de processus arbitraires.

> **Aperçu de recherche bêta**
>
> Le Sandbox Runtime est un aperçu de recherche développé pour [Claude Code](https://www.claude.com/product/claude-code) afin de permettre des agents IA plus sûrs. Il est mis à disposition sous forme d'aperçu open source précoce pour aider l'écosystème au sens large à construire des systèmes agentiques plus sécurisés. S'agissant d'un aperçu de recherche précoce, les API et les formats de configuration sont susceptibles d'évoluer. Nous accueillons favorablement les retours et les contributions pour rendre les agents IA plus sûrs par défaut !

## Installation

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

## Utilisation de 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
```

## Aperçu

Ce paquet fournit une implémentation de bac à sable autonome qui peut être utilisée à la fois comme outil CLI et comme bibliothèque. Il est conçu selon une philosophie **sécurisée par défaut** adaptée aux cas d'usage courants des développeurs : les processus démarrent avec un accès minimal, et vous n'ouvrez explicitement que les brèches dont vous avez besoin.

**Capacités clés :**

- **Restrictions réseau** : contrôlez quels hôtes/domaines sont accessibles via HTTP/HTTPS et d'autres protocoles
- **Restrictions du système de fichiers** : contrôlez quels fichiers/répertoires peuvent être lus/écrits
- **Restrictions des sockets Unix** : contrôlez l'accès aux sockets IPC locaux
- **Surveillance des violations** : sur macOS, exploitez le magasin de journaux de violations du bac à sable du système pour des alertes en temps réel

### Exemple de cas d'usage : sandboxer les serveurs MCP

Un cas d'usage clé consiste à sandboxer les serveurs Model Context Protocol (MCP) afin de restreindre leurs capacités. Par exemple, pour sandboxer le serveur MCP de système de fichiers :

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

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

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

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

Puis configurez les restrictions dans `~/.srt-settings.json` :

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

Désormais, le serveur MCP sera bloqué lors de l'écriture vers le chemin refusé :

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

## Fonctionnement

Le bac à sable utilise des primitives au niveau du système d'exploitation pour appliquer des restrictions qui s'appliquent à l'ensemble de l'arborescence des processus :

- **macOS** : utilise `sandbox-exec` avec des [profils Seatbelt](https://reverse.put.as/wp-content/uploads/2011/09/Apple-Sandbox-Guide-v1.0.pdf) générés dynamiquement
- **Linux** : utilise [bubblewrap](https://github.com/containers/bubblewrap) pour la conteneurisation avec isolation de l'espace de noms réseau
- **Windows** : exécute le processus isolé sous un compte utilisateur local dédié `srt-sandbox`, avec une clôture de sortie [Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/windows-filtering-platform-start-page) indexée sur le SID de ce compte, un jeton à écriture restreinte et des ACE explicites sur l'arborescence de travail

0d1c612947c798aef48e6ab4beb7e8544da9d41a-4096x2305

### Modèle d'isolation double

L'isolation du système de fichiers et l'isolation réseau sont toutes deux nécessaires pour un bac à sable efficace. Sans isolation des fichiers, un processus compromis pourrait exfiltrer des clés SSH ou d'autres fichiers sensibles. Sans isolation réseau, un processus pourrait s'échapper du bac à sable et obtenir un accès réseau non restreint.

**Isolation du système de fichiers** applique des restrictions de lecture et d'écriture :

- **Lecture** (schéma refuser-puis-autoriser) : par défaut, l'accès en lecture est autorisé partout. Vous pouvez refuser de larges zones (par exemple, `/Users`) puis réautoriser des chemins spécifiques à l'intérieur de celles-ci (par exemple, `.`). `allowRead` a la priorité sur `denyRead` — l'inverse de l'écriture, où `denyWrite` a la priorité sur `allowWrite`. Une entrée `denyRead` plus spécifique que la région `allowRead` dans laquelle elle se trouve (par exemple `denyRead: ["**/.env"]` ou `["./secrets"]` avec `allowRead: ["."]`) reste refusée.
- **Écriture** (schéma autoriser-uniquement) : par défaut, l'accès en écriture est refusé partout. Vous devez explicitement autoriser des chemins (par exemple, `.`, `/tmp`). Une liste d'autorisation vide signifie aucun accès en écriture.

**Isolation réseau** (schéma autoriser-uniquement) : par défaut, tout accès réseau est refusé. Vous devez explicitement autoriser des domaines. Une liste allowedDomains vide signifie aucun accès réseau. Le trafic réseau est acheminé via des serveurs proxy s'exécutant sur l'hôte :

- **Linux** : les requêtes sont acheminées via le système de fichiers par le biais d'un socket de domaine Unix. L'espace de noms réseau du processus isolé est entièrement supprimé, de sorte que tout le trafic réseau doit passer par les proxys s'exécutant sur l'hôte (à l'écoute sur des sockets Unix montés par bind dans le bac à sable)

- **macOS** : le profil Seatbelt n'autorise la communication que vers un port localhost spécifique. Les proxys écoutent sur ce port, créant un canal contrôlé pour tout accès réseau

- **Windows** : un ensemble de filtres WFP à l'échelle de la machine bloque les connexions sortantes effectuées par les processus s'exécutant sous le compte `srt-sandbox`, à l'exception du loopback vers la plage de ports proxy. Les proxys écoutent dans cette plage, créant un canal contrôlé pour tout accès réseau. Les filtres ne suivent pas un processus isolé qui place un jeton différent sur un thread avant de créer un socket, ni le trafic qu'un service système transporte en son nom ; voir les [limitations connues](#known-limitations) de Windows

Le trafic HTTP/HTTPS (via proxy HTTP) et les autres trafics TCP (via proxy SOCKS5) sont tous deux médiés par ces proxys, qui appliquent vos listes d'autorisation et de refus de domaines.

Pour plus de détails sur le bac à sable dans Claude Code, voir :

- [Documentation sur le bac à sable de Claude Code](https://docs.claude.com/en/docs/claude-code/sandboxing)
- [Au-delà des invites d'autorisation : rendre Claude Code plus sûr et plus autonome](https://www.anthropic.com/engineering/claude-code-sandboxing)

## Architecture

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

## Utilisation

### En tant qu'outil CLI

La commande `srt` (Anthropic Sandbox Runtime) encapsule n'importe quelle commande avec des frontières de sécurité :

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

Le fichier de paramètres est facultatif — sans fichier à `~/.srt-settings.json`, `srt` s'exécute avec les valeurs par défaut intégrées : aucun accès réseau, aucune écriture en dehors des chemins d'écriture par défaut, et des lectures non restreintes. Un fichier de paramètres qui _est_ présent mais vide, illisible ou invalide constitue une erreur : `srt` le signale et quitte plutôt que de revenir à ces valeurs par défaut, qui correspondent à une configuration différente et non à une configuration plus faible — un repli supprimerait les règles `denyRead`, `allowRead` et d'identifiants du fichier, ainsi que tout le reste de ce qu'il spécifie. Il en va de même pour un fichier nommé via `--settings`, qui doit également exister.

#### Mise à jour de la configuration pendant l'exécution de la commande : `--control-fd`

`--control-fd <fd>` lit les mises à jour de configuration depuis un descripteur que l'appelant a déjà ouvert, un objet JSON par ligne, de la même forme que le fichier de paramètres. Chaque ligne remplace l'intégralité de la configuration et est validée selon le même schéma ; une ligne constitue donc une configuration complète plutôt qu'un correctif : `network` et `filesystem` sont requis, et une clé omise dans la ligne revient à sa valeur par défaut.

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

Ce qu'une ligne acceptée modifie une fois la commande en cours d'exécution :

- Les listes réseau — `network.allowedDomains`, `deniedDomains` (avec
  `deniedDomainReasons`) et `deniedResolvedAddresses` — prennent effet à la
  connexion suivante, sur toutes les plateformes : le proxy les consulte à
  chaque requête, et la vérification des adresses résolues est reconstruite à
  partir de la même ligne. Il en va de même pour
  `network.mitmProxy` et `network.tlsTerminate.excludeDomains`, qu'il lit
  également à chaque requête.
- `credentials.sigv4` prend effet à la requête suivante, à condition que srt
  ait démarré avec un bloc `credentials` : le hook de signature n'est installé
  que dans ce cas, et lit les politiques à chaque requête plutôt que de les
  capturer.
- Rien d'autre ne change. Les règles de système de fichiers figurent déjà dans
  le profil seatbelt, l'argv bubblewrap ou les ACE Windows, les masques
  d'identifiants ont été construits lors de l'enveloppement de la commande, et
  les serveurs proxy en cours d'exécution ont capturé `network.parentProxy`,
  ainsi que le fait que TLS soit terminé ou non, à leur démarrage.
- Sous Windows, srt détecte une ligne dont l'ensemble d'accès aux fichiers
  (`filesystem.*` conjointement avec `credentials.files`) diffère de celui
  appliqué au démarrage, et ne le signale que sous `SRT_DEBUG` : l'octroi ACL
  est valable pour toute la session, donc l'ensemble appliqué au démarrage
  reste en vigueur. Le reste de la ligne est appliqué comme indiqué ci-dessus.

Comment srt lit le canal, et ce qu'il refuse :

- Le descripteur doit être un entier **3 ou supérieur** et lisible — `0`-`2`
  sont les flux standard. srt se termine par une erreur au lieu d'exécuter la
  commande lorsqu'il ne peut pas lire le descripteur qui lui a été fourni,
  afin qu'un canal mort ne passe jamais pour un canal actif. Un canal qui meurt
  avant d'avoir livré une seule mise à jour entraîne la commande avec lui ; un
  canal qui meurt après le signale et laisse la commande s'exécuter sous la
  configuration appliquée en dernier.
- Une ligne qui n'est pas une configuration valide est signalée sur stderr et
  ignorée ; la configuration précédente reste en vigueur. La ligne elle-même
  est envoyée au journal de débogage plutôt qu'au terminal, et une ligne vide
  est ignorée silencieusement.
- srt ne commence à lire qu'une fois le bac à sable démarré, de sorte qu'une
  mise à jour écrite avant ce moment attend dans le canal plutôt que d'être
  perdue — et ne peut pas être écrasée par la configuration avec laquelle le
  bac à sable démarre. Une telle ligne peut être lue pendant que la commande
  est encore en cours d'enveloppement, et constitue alors la configuration avec
  laquelle elle est enveloppée, règles de système de fichiers incluses. Le fait
  qu'elle soit lue aussi tôt dépend de la durée de l'enveloppement (sous Linux,
  un glob de refus sur une grande arborescence suffit), donc une règle sous
  laquelle la commande doit démarrer doit figurer dans le fichier de
  paramètres.
- srt **se termine avec la commande enveloppée** et n'attend pas que
  l'écrivain ferme le descripteur. La fin de l'entrée n'est pas non plus une
  erreur : la commande continue de s'exécuter sous la configuration appliquée
  en dernier.
- Fournissez à srt une **extrémité dédiée et en lecture seule**. srt place un
  pipe ou une socket en mode non bloquant, et cet indicateur réside sur la
  description de fichier ouverte, donc tout autre détenteur de la même
  description — un `exec 3<fifo` d'un shell, un `pass_fds` d'un descripteur que
  le parent continue d'utiliser — reçoit `EAGAIN` de ses propres lectures
  bloquantes à partir de ce moment.
- Sous macOS et Linux, la commande mise en bac à sable ne reçoit pas le
  descripteur : srt pointe cet emplacement vers `/dev/null` pour la commande,
  afin que rien à l'intérieur du bac à sable ne puisse lire les mises à jour ni
  écrire une configuration qui lui soit propre. Sous Windows, la commande est
  lancée avec les trois flux standard seuls, donc le descripteur de contrôle ne
  figure pas parmi les descripteurs qui lui sont transmis.

### Comme proxy autonome avec un décideur externe : `srt proxy`

`srt proxy` (ou l'exécutable monofichier `srt-proxy` construit par `bun run build:srt-proxy`) exécute uniquement le proxy HTTP de SRT, sans processus enfant mis en bac à sable, pour un hôte qui exécute la charge de travail ailleurs. Il accepte les connexions sur une socket d'écoute fournie par l'hôte, termine chaque CONNECT dans le processus, et ne transmet une requête que lorsqu'un processus décideur distinct, joint via un autre descripteur hérité, l'autorise. Voir [docs/srt-proxy.md](https://github.com/anthropic-experimental/sandbox-runtime/blob/main/docs/srt-proxy.md) pour la ligne de commande, le protocole du décideur et le modèle de sécurité.

### Comme bibliothèque

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

**Attribution des violations (`commandId` / `commandText`).** Les violations observées pendant l'exécution d'une commande encapsulée (lignes de journal seatbelt, événements seccomp, refus du proxy) sont stockées sous une clé d'attribution, et `annotateStderrWithSandboxFailures(key, stderr)` / `getViolationsForCommand(key)` les recherchent par cette même clé. Par défaut, la clé est la chaîne encapsulée elle-même. Passez un `commandId` opaque par invocation (par ex. un id d'utilisation d'outil) pour indexer par celui-ci à la place — recommandé : les clés sont comparées sur leurs 100 premiers caractères, donc de longues commandes partageant un préfixe seraient sinon attribuées de manière croisée, et une réexécution du même texte hériterait des événements de l'exécution précédente. Si la chaîne que vous _exécutez_ n'est pas la commande que l'invocation _représente_ (par ex. vous encapsulez un `source <snapshot> && eval '<cmd>'` assemblé), passez aussi `commandText: '<cmd>'` : c'est ce à quoi les motifs de commande `ignoreViolations` sont comparés et ce que chaque violation rapporte comme `command`. Un `commandId` que vous passez à `wrapWithSandbox` doit être la même chaîne non vide que vous passez ensuite à `annotateStderrWithSandboxFailures` / `getViolationsForCommand` ; une chaîne vide est traitée comme absence de `commandId`, donc la clé est la commande.

Seule la clé est tronquée à 100 caractères. Depuis la v0.0.76, le `command` rapporté — et le texte auquel les motifs de commande `ignoreViolations` sont comparés — est la commande entière pour une invocation encapsulée sans `commandId`, et non ses 100 premiers caractères ; un motif ne peut donc que supprimer davantage qu'auparavant, jamais moins. Une clé d'attribution qu'aucune invocation de ce processus n'a enregistrée (les porteurs sont modifiables depuis l'intérieur du bac à sable) est rapportée assainie et tronquée à cette même longueur de clé.

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

**Interrogation sur un hôte qu'aucune règle ne décide (le callback ask).** Le deuxième argument de `SandboxManager.initialize` est un `SandboxAskCallback` facultatif. Il est interrogé au sujet d'une destination que ni `network.deniedDomains`, ni `network.allowedDomains`, ni une liste d'autorisation par commande (section suivante) n'a décidée, et il n'est jamais interrogé sous `network.strictAllowlist`. Sans callback, une telle destination est refusée. Le callback se résout en l'une des valeurs suivantes :

- `true` - autoriser la connexion. Seule la valeur `true` autorise.
- `false` - la refuser. La ligne de violation rapporte la raison générique `user denied`.
- `{ allow: false, reason: '...' }` - la refuser, et rapporter `reason` dans la ligne de violation à la place du texte générique, afin que quiconque lit le bloc `<sandbox_violations>` (y compris un modèle) apprenne pourquoi et quoi faire à la place. Le client sandboxé le lit également, comme phrase de statut du `403` qui répond à son CONNECT.

Toute autre réponse refuse, qu'elle soit truthy ou non, et rapporte la raison générique. Cela inclut un objet qui porte une `reason` sans dire `allow: false`, tel que `{ allow: true, reason: '...' }` : sa raison n'est pas rapportée.

La raison est assainie avant d'être stockée, comme le reste d'une ligne de violation. Chaque suite de caractères de contrôle (sauts de ligne et tabulations inclus) ou de caractères invisibles (caractères de largeur nulle, dont le joiner, et contrôles bidi) devient un espace ; `<` et `>` sont supprimés, de sorte que `re-run with <host> listed` est stocké comme `re-run with host listed` ; les extrémités sont rognées. Le résultat est tronqué à 500 caractères, comptés en unités de code UTF-16 comme le fait `String.prototype.length`. Une raison dont il ne reste rien après cela retombe sur `user denied`. Rédigez-la sous forme d'une seule ligne de texte brut.

**Changement de comportement dans la première version après 0.0.79 :** le filtre autorisait auparavant sur toute réponse truthy, de sorte qu'un callback qui se résolvait en une valeur truthy autre que `true` (`1`, une chaîne, n'importe quel objet) autorisait la connexion. Il refuse désormais. Pour la même raison, `{ allow: false, reason }` renvoyé à une version plus ancienne y serait lu comme une autorisation, car un objet est truthy. `SandboxManager.askCallbackDenyReason` vaut `true` sur une version qui comprend l'objet : vérifiez-le avant d'en renvoyer un, et refusez avec un simple `false` là où il est absent.

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

**Listes d'autorisation réseau par commande (`registerCommandNetworkLists`).** Une invocation peut porter sa propre liste d'autorisation, en plus de celle configurée, pendant toute sa durée d'exécution :

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

Les entrées utilisent la grammaire et le matcher de `network.allowedDomains` et bénéficient de la même validation. `registerCommandNetworkLists` lève une exception sur une entrée invalide, et sur un `commandId` de moins de 22 caractères (un surrogate non apparié ne compte pas). Enregistrer à nouveau un id remplace sa liste ; `unregisterCommandNetworkLists` est une opération sans effet pour un id qui n'en possède pas ; `reset()` supprime tous les enregistrements.

L'ordre d'évaluation pour une connexion est le suivant :

1. une correspondance avec `network.deniedDomains` refuse ;
2. une correspondance avec `network.allowedDomains` autorise ;
3. `network.strictAllowlist` refuse ;
4. une correspondance dans la liste enregistrée pour l'id présenté par la connexion autorise ;
5. le callback ask décide s'il en existe un, sinon la connexion est refusée.

Ainsi, une entrée par commande ne supplante jamais une entrée `deniedDomains` configurée, et est entièrement ignorée sous `strictAllowlist`. Elle n'entre jamais non plus dans `network.*` : `getConfig()` et `getNetworkRestrictionConfig()` ne l'affichent pas, et la portée `injectHosts` par défaut d'un identifiant masqué, qui est `network.allowedDomains`, ne s'élargit pas. Un hôte autorisé de cette manière passe tout de même par la vérification de l'adresse résolue lorsqu'il est contacté, et un littéral IP dans une liste par commande n'y ajoute aucune exemption.

Ce que l'id doit être, et ce que cette fonctionnalité n'est pas : le proxy apprend à quelle invocation appartient une connexion à partir du nom d'utilisateur du proxy, et ce nom d'utilisateur est présenté par le client à l'intérieur du bac à sable. L'id est donc la **seule** chose qui lie une connexion à une liste d'autorisation. Il **doit** être impossible à deviner : au moins 128 bits d'aléa, jamais un compteur, un horodatage ou quoi que ce soit dérivé de la commande. Un processus en bac à sable qui présente l'id d'une autre invocation active obtient les autorisations de cette invocation ; il s'agit donc d'attribution, et non d'une frontière entre commandes concurrentes d'une même session. Enregistrez juste avant de lancer la commande encapsulée, et désenregistrez lorsque l'enfant se termine ou n'a jamais démarré : un enregistrement qui survit à sa commande élargit la fenêtre pendant laquelle son id vaut la peine d'être présenté. Comme pour toute clé d'attribution, seuls les 100 premiers caractères d'un id entrent en compte. Gardez les ids en ASCII : une liste sous un id non-ASCII dont la forme encodée ne tient pas dans le nom d'utilisateur du proxy (255 octets) s'enregistre et ne s'applique jamais.

Aucune liste ne s'applique lorsque `network.httpProxyPort` désigne un proxy externe : le wrap ne fournit aucun nom d'utilisateur à ce proxy, donc aucune connexion ne porte d'id. `registerCommandNetworkLists` réussit tout de même (et le signale sur une ligne sous `SRT_DEBUG`), et chaque connexion est décidée comme si aucune liste n'existait.

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

## Configuration

### Emplacement du fichier de paramètres

Par défaut, le runtime du bac à sable recherche la configuration dans `~/.srt-settings.json`. Vous pouvez spécifier un chemin personnalisé à l'aide de l'option `--settings` :

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

### Exemple de configuration complet

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

### Options de configuration

#### Configuration réseau

Utilise un **modèle de type liste blanche** - tout accès réseau est refusé par défaut.

- `network.allowedDomains` - Tableau des domaines autorisés (prend en charge les jokers comme `*.example.com`). Tableau vide = aucun accès réseau. Un suffixe `:port` facultatif (`api.example.com:443`, `*.example.com:8443`) restreint une entrée à ce port de destination ; les entrées sans port correspondent à n'importe quel port.
  - Les littéraux IPv6 doivent être entre crochets, à la manière de la RFC 3986 : `[::1]`, `[2001:db8::1]:443`. Une entrée à plusieurs deux-points sans crochets est rejetée comme ambiguë (`2001:db8::1:443` est lui-même une adresse valide).
- `network.deniedDomains` - Tableau des domaines refusés (vérifié en premier, prioritaire sur allowedDomains). Même suffixe `:port`, et un `*` seul (ou `*:22`) est accepté pour tout refuser.
- `network.deniedDomainReasons` - Table facultative associant une entrée de `deniedDomains` (correspondance par chaîne exacte) à une raison destinée au modèle qui apparaît dans la ligne `<sandbox_violations>` lorsque cette entrée bloque une connexion — indiquez ce qui est bloqué et l'alternative autorisée (par ex. `{"github.com:22": "Les push SSH vers GitHub sont bloqués ; utilisez un remote https://"}`). Les entrées sans raison rapportent une raison générique. Pour les destinations SSH (port 22), la raison est également transmise en bande : un client SSH tunnelisé via un ProxyCommand SOCKS sans authentification (par ex. `nc -X 5` de BSD) reçoit une déconnexion SSH avant l'échange de clés dont la description est la raison, qu'OpenSSH affiche telle quelle — gardez ces raisons sous ~400 caractères ASCII, à l'impératif en premier, car OpenSSH tronque et échappe les caractères non-ASCII. Un client qui s'authentifie réellement, comme le fait le `GIT_SSH_COMMAND` injecté par srt, reçoit la raison sur n'importe quel port comme phrase de statut du `403` qui répond à son CONNECT, ce que cette commande, et bien des clients HTTP, affichent. Là, elle est nettoyée et tronquée comme dans la ligne de violation, et chaque caractère non-ASCII devient `?`, car les clients ne s'accordent pas sur la façon de lire un tel caractère dans une ligne de statut.
- `network.allowLocalBinding` - Permet aux commandes sandboxées d'utiliser directement les ports locaux (booléen, par défaut : false). macOS : se lier et accepter sur n'importe quel port local, et se connecter à `localhost` sur n'importe quel port. Windows : se connecter aux adresses de bouclage sur n'importe quel port TCP ou UDP ; cela fait partie de l'installation à l'échelle de la machine, voir [Serveurs locaux sous Windows](#local-servers-on-windows). Linux : ignoré — le sandbox dispose de son propre espace de noms réseau, dont le bouclage est toujours utilisable et n'est pas celui de l'hôte.

**Vérification des adresses résolues.** Les listes d'autorisation/refus correspondent par _nom_, mais quiconque contrôle le DNS d'un nom autorisé (ou de n'importe quel label sous un joker autorisé) contrôle ce vers quoi il résout. Ainsi, avant de composer directement un **nom d'hôte** autorisé, le proxy le résout une fois, écarte toute adresse appartenant à un ensemble refusé, et se connecte à une adresse survivante (l'adresse qui a passé la vérification est celle composée — il n'y a pas de seconde résolution). Si aucune ne survit, la connexion est refusée comme tout autre refus de politique : HTTP/CONNECT reçoivent `403` (`X-Proxy-Error: blocked-by-sandbox-runtime`, la raison dans le corps et, pour un CONNECT, comme phrase de statut), SOCKS reçoit « connection not allowed by ruleset », et une ligne `deny network-outbound host:port (resolved to a loopback address)` — nommant la classe d'adresse (bouclage, lien-local, celle de cet hôte, métadonnées cloud, sur liste de refus, sur liste, …), et non l'adresse elle-même, que seul le journal de débogage contient — est enregistrée dans le magasin de violations.

---

[Read more](https://github.com/anthropic-experimental/sandbox-runtime)
Télécharger l’outil