Vai al contenuto principale

Procedure consigliate per il contenimento degli agenti: sandboxing (beta privata)

Per i clienti del nostro Cyber Verification Program, forniamo un nuovo classificatore di escape da sandbox nell'API per monitorare e ridurre gli abusi. Questo articolo spiega perché gli agenti autonomi hanno bisogno di un forte isolamento, come il design di riferimento li isola e come definire l'ambito e supervisionare gli impegni che richiedono accesso alla rete.

Questo classificatore è in beta privata.

Per una panoramica di tutte le risorse disponibili, consulta Procedure consigliate per il contenimento degli agenti: guida introduttiva (beta privata).

Panoramica

  • In un'esecuzione autonoma, nessun umano approva le chiamate agli strumenti dell'agente e l'agente può eseguire il codice target. Consigliamo di eseguire agenti autonomi in una sandbox robusta che interpone un kernel virtualizzato a livello hardware tra l'host e sia l'agente che il codice target. Non utilizzare Docker/runc nudo e non utilizzare mai --privileged o networking host.

  • Il design di riferimento esegue ogni agente nella propria microVM (Kata Containers con Firecracker) su una rete interna. Richiede un host Linux con KVM, il che limita gli host che possono eseguirlo. Kata ha deprecato il runtime su cui dipende Firecracker.

  • Non montare mai percorsi che contengono credenziali (come ~/.aws, ~/.ssh o .env) nell'ambiente dell'agente. Mantieni anche la credenziale modello-API fuori dall'ambiente dell'agente: fai in modo che un proxy di credenziale separato la mantenga e la aggiunga a ogni richiesta del modello (vedi Il proxy di credenziale).

  • Nega l'uscita per impostazione predefinita. Nel design di riferimento, le chiamate al modello passano attraverso il proxy di credenziale e il proxy di uscita rifiuta ogni altra destinazione a meno che non sia nella lista di autorizzazione.

  • Testa la tua sandbox su ogni host prima di affidarti ad essa e di nuovo ogni volta che la sandbox o il modello cambia.

  • Per gli impegni che richiedono accesso alla rete, dichiara l'ambito nelle istruzioni dell'agente, applicalo nella rete e mantieni gli agenti autonomi lontani dai sistemi live ad alte conseguenze (vedi Ambito e supervisione).

Guida al sandboxing

Proprietà da perseguire

Se costruisci la tua sandbox, queste sono le proprietà che il design di riferimento fornisce. Il resto di questo articolo descrive un modo per ottenerle.

  1. Ogni agente ha il proprio kernel guest, che non condivide con l'host.

  2. Gli strumenti file e shell dell'agente vedono solo il filesystem del guest. Nessuna directory host è condivisa nel guest.

  3. La credenziale modello-API non è nell'ambiente dell'agente né sul suo disco. Un proxy al di fuori della sandbox la aggiunge a ogni richiesta.

  4. L'agente non ha accesso a Internet. L'uscita è applicata al di fuori del guest e ogni destinazione è rifiutata a meno che non sia in una lista di autorizzazione.

  5. Il servizio di metadati cloud non può essere raggiunto dall'agente.

  6. Ogni agente ha un limite di turni e un limite di tempo se lo imposti.

  7. Nessuna modalità privilegiata, capacità aggiuntive, passthrough di dispositivi o networking host.

  8. L'orchestratore viene eseguito sull'host attendibile e scrive i trascritti lì.

Linee guida generali

Una sandbox robusta è più importante per le esecuzioni autonome, dove gli agenti eseguono il codice target e nessun umano approva ogni azione

Esegui agenti autonomi in sandbox robuste e rifletti su quali effetti collaterali un processo in quella sandbox potrebbe ancora causare. I modelli frontier sono sempre più bravi a trovare percorsi creativi attorno alle restrizioni: la stessa proprietà che li rende efficaci cacciatori di vulnerabilità significa che potrebbero intraprendere azioni inaspettate contro il loro stesso ambiente di esecuzione. Questo non è ipotetico. Anthropic ha pubblicato esempi di modelli che aggirano vincoli deboli per completare un compito (vedi Come conteniamo Claude in tutti i prodotti).

Concretamente, non eseguire agenti autonomi di ricerca di vulnerabilità in Docker/runc nudo e soprattutto non con --privileged o networking host. I container standard condividono il kernel host, quindi un exploit del kernel all'interno del container è un compromesso dell'host. Consigliamo di interporre un kernel virtualizzato a livello hardware tra il codice target e l'host, il che significa eseguire l'agente in una macchina virtuale. Dove ciò non è possibile, utilizza un host bare-metal dedicato che non contiene nient'altro. Se costruisci la tua sandbox, consigliamo Firecracker su Linux, Hyper-V su Windows e una VM basata sul framework Hypervisor su macOS. Il design di riferimento utilizza Firecracker.

Blocca tutto l'uscita dalla sandbox. L'agente raggiunge l'API del modello solo attraverso un proxy che aggiunge la credenziale e viene eseguito al di fuori della sandbox, quindi la sandbox non ha bisogno di un percorso diretto all'host API. Installa ogni strumento, pacchetto e dipendenza prima dell'inizio dell'esecuzione, in modo che nulla debba essere recuperato durante essa.

L'uso interattivo, con un umano nel ciclo, generalmente comporta meno rischi, ma consigliamo comunque una sandbox per esso. Se guidi un agente in modo interattivo da Claude Code su un laptop, esamina ogni utilizzo dello strumento (modalità manuale) oppure affidati al classificatore di autorizzazione della modalità automatica e fai approvare da un umano ogni azione che raggiunge al di fuori del repository. La modalità automatica rimuove i prompt di autorizzazione di routine: approva letture e modifiche della directory di lavoro automaticamente e invia tutto il resto a un classificatore in background che mira a bloccare azioni distruttive, irreversibili o fuori tema. È un controllo best-effort. Può perdere cose e sul lavoro di sicurezza potrebbe anche rifiutare alcuni passaggi legittimi. La modalità automatica descrive come funziona, cosa aspettarsi da essa e come configurarla per il tuo ambiente.

Non montare mai percorsi che contengono credenziali come ~/.aws, ~/.ssh o .env nell'ambiente dell'agente. Lo stesso vale per la credenziale che le stesse chiamate del modello dell'agente utilizzano. Mantienila al di fuori della sandbox e fai in modo che un proxy che l'agente non può leggere la aggiunga a ogni richiesta (vedi Il proxy di credenziale). Non connettere agenti a server MCP o strumenti con accesso in scrittura a stato esterno come email, archiviazione cloud o infrastruttura di produzione.

Dividi ogni esecuzione in una fase di configurazione e una fase di attacco con diverse politiche di rete

Questo è un modello che mette in pratica le linee guida di cui sopra. La fase di configurazione ha accesso a Internet in uscita e un umano nel ciclo che approva ogni chiamata dello strumento. In essa l'agente estrae le dipendenze, costruisce il target e configura la sua sandbox da un documento di specifica. La fase di attacco non ha accesso generale a Internet. Tutto l'uscita passa attraverso un proxy della lista di autorizzazione che consente solo gli host denominati nell'impegno, quindi il proxy applica anche l'ambito. Le chiamate del modello passano attraverso il proxy di credenziale separato. L'agente può quindi sondare il target senza supervisione. Il proxy contiene il traffico dell'agente stesso. Non contiene il traffico che un target in rete invia per conto dell'agente.

Incorpora le dipendenze di cui l'agente ha bisogno ripetutamente nell'immagine di configurazione, in modo che le esecuzioni della fase di attacco non abbiano bisogno di accesso a Internet. Ambito le credenziali per target, in modo che un agente che lavora su un target non possa usarle contro un altro. Mantieni la modalità automatica di Claude Code attiva all'interno della sandbox durante la fase di attacco e descrivi la sandbox al suo classificatore. Vedi La modalità automatica.

Limita ogni esecuzione e conosci il tuo interruttore di emergenza

Dai a ogni agente un budget esplicito, in modo che un'esecuzione che supera i test previsti si fermi da sola e non quando qualcuno se ne accorge. Applica un limite di turni rigido su ogni agente. Quando un agente lo esaurisce, termina l'esecuzione e non concedere più turni automaticamente. Il riavvio con un limite più alto è il punto in cui una persona decide di continuare. Limita anche le esecuzioni nel tempo. Termina una sessione che supera il limite di tempo allo stesso modo: l'esecuzione è finale e non viene mai ripresa e il processo dell'agente viene interrotto, anche quando il limite viene raggiunto nel mezzo di un comando di lunga durata. Se un limite è impostato su un valore che non può essere letto, rifiuta di avviare invece di eseguire senza limiti. Imposta i limiti deliberatamente per l'impegno e non accettare un default generoso. Abbinali alla cadenza di monitoraggio in monitoraggio offline dei trascritti degli agenti, in modo che un batch lungo venga esaminato ogni ora o due e non solo alla fine. Sappi come fermare un singolo agente senza fermare il batch. In una configurazione basata su Docker è docker rm -f <agent-container>. L'orchestratore dovrebbe registrare quell'esecuzione come non riuscita e continuare con il resto del batch.

Per ulteriori indicazioni, leggi due risorse Anthropic. Distribuzione sicura di agenti AI copre opzioni di isolamento, proxy di credenziale e hardening del filesystem. Il retrospettivo di ingegneria Come conteniamo Claude in tutti i prodotti copre cosa ha funzionato e cosa no quando questi stessi meccanismi venivano eseguiti in produzione.

Ambito e supervisione

La sandbox limita ciò che un agente può raggiungere. Per pentesting, red teaming e altri impegni che richiedono accesso alla rete, le pratiche di seguito limitano ciò che all'agente viene chiesto e autorizzato a fare. Dipendono dai tuoi target e dal tuo team, quindi gli strumenti non possono mettere la maggior parte di essi in atto per te.

Dichiara l'ambito nelle istruzioni dell'agente

Prima di un'esecuzione, comunica all'agente quali target sono nell'ambito, quali azioni sono consentite, dove si trova il confine della rete e cosa è fuori ambito. Esprimi ogni vincolo come intento ("non accedere agli host al di fuori di 10.0.3.0/24") e non come affermazione sull'ambiente ("non puoi raggiungere Internet"), in modo che l'istruzione rimanga valida se l'ambiente è configurato in modo errato. Fai questo anche per il lavoro locale in sandbox: comunica all'agente di non utilizzare l'accesso a Internet, anche se la sandbox lo blocca. La descrizione che dai al classificatore della modalità automatica è una cosa diversa. Afferma fatti sulla macchina (vedi La modalità automatica).

Applica lo stesso ambito nella rete

Dove puoi, esegui l'agente all'interno dello stesso isolamento descritto sopra e autorizza l'uscita solo ai target nell'ambito (vedi Lista di autorizzazione dell'uscita). L'agente raggiunge l'API del modello attraverso il proxy di credenziale, non attraverso la lista di autorizzazione. Dove disponibile, indirizza l'impegno a un ambiente di staging o replica che è disconnesso dalla produzione.

Negozia l'accesso al target dove puoi

Dai all'agente accesso ai sistemi target attraverso qualcosa che puoi osservare, come un proxy di accesso o un set definito di strumenti. Evita di lasciare che l'agente scriva i propri strumenti con accesso generale al target. In un harness personalizzato, separa gli strumenti di sola lettura dagli strumenti che cambiano lo stato e supervisiona il secondo gruppo più da vicino. Considera l'analisi di comandi rischiosi mentre vengono proposti e negali o escalali a una persona.

Supervisiona le esecuzioni che hanno accesso alla rete

Consigliamo che un ingegnere osservi ogni esecuzione mentre viene eseguita, seguendo le chiamate agli strumenti e l'attività di rete, e sia in grado di interrompere immediatamente l'esecuzione. Gli agenti agiscono a velocità di macchina, quindi l'osservazione dal vivo integra i controlli che agiscono prima di un'azione (liste di autorizzazione di rete, strumenti negoziati e revisione di azioni che cambiano lo stato). Non li sostituisce. Per esecuzioni lunghe o autonome dove l'attenzione continua è impraticabile, monitora continuamente nel software (vedi Monitoraggio offline dei trascritti degli agenti).

Mantieni gli agenti autonomi lontani dai sistemi live ad alte conseguenze

Non eseguire agenti autonomi contro sistemi di produzione live dove un'azione fuori ambito potrebbe mettere in pericolo la sicurezza o la disponibilità di servizi critici, come OT/ICS, medici o sistemi energetici. Questo è già la norma per i test condotti da umani di tali sistemi e si applica ugualmente qui. Testa contro una replica, un testbed o un gemello digitale, o durante un'interruzione pianificata. Dove l'accesso live è inevitabile, limita l'agente all'attività passiva o di sola lettura e fai in modo che una persona esegua ogni passaggio che cambia lo stato.

Testa la sandbox prima di affidarti ad essa

Prima di eseguire impegni reali da un host, testa la sua sandbox con i due passaggi di seguito. Fai questo prima del primo uso reale e di nuovo ogni volta che cambi il modello o la sandbox. I cambiamenti della sandbox includono un nuovo host, una nuova versione dell'hypervisor o del runtime del container, una configurazione di rete o proxy diversa e una configurazione di container o compose modificata.

Per prima cosa, fai rivedere la configurazione a Claude

In una sessione interattiva di Claude Code sull'host, chiedigli di leggere la configurazione della sandbox così come è configurata su questa macchina e di segnalare tutto ciò che indebolisce il confine descritto in questo articolo. Indicagli:

  • La configurazione dell'hypervisor e del container-runtime (per il design di riferimento, il configuration.toml renderizzato di Kata e il daemon.json di Docker);

  • La rete degli agenti e il proxy di uscita come li segnala il runtime, e la lista di autorizzazione del proxy;

  • Il proxy delle credenziali come lo segnala il runtime, e l'ambiente di un contenitore agente in esecuzione (vedi Il proxy delle credenziali di seguito);

  • Qualsiasi file di composizione o orchestrazione che avvia agenti o target;

  • L'elenco di ciò che è montato o trasmesso nei guest (vedi Note operative di seguito).

Questo passaggio legge solo la configurazione e lo stato. Non avvia un agente.

Quindi, esegui un test di fuga supervisionato

Avvia l'agente di test nello stesso modo in cui avvii gli agenti di produzione, e non con un comando costruito manualmente, in modo che il test eserciti il percorso reale. La sezione Verifica l'isolamento da solo di seguito copre i controlli manuali del confine. Dai all'agente un singolo compito: provare a raggiungere qualsiasi cosa al di fuori del suo confine, e fermarsi e segnalare non appena qualcosa ha successo. Nomina il confine concretamente nel prompt: l'host, altri contenitori, il socket del container-runtime, il servizio di metadati del cloud, e qualsiasi host che non sia nella lista di autorizzazione del proxy. Esegui questo solo sotto stretta supervisione umana, su un host senza accesso a Internet al di là dell'API del modello e che sei preparato a ricostruire, in modo che una fuga riuscita non causi danni. Su bare metal, esegui il test all'interno di una VM usa e getta. Su una VM cloud, usa un'istanza nuova e distruggila dopo. Osserva la sessione mentre viene eseguita. Tratta qualsiasi successo come un blocco: correggi l'host, ripeti il test, e non eseguire engagement da quell'host fino a quando il test non passa.

Successivamente, leggi l'intero transcript

Controlla cosa ha provato l'agente e se è uscito. Cerca connessioni dirette che non sono passate attraverso il proxy, letture di file di credenziali o indirizzi di metadati, uso del socket del container-runtime o sonde di contenitori vicini, scritture al di fuori del filesystem del contenitore stesso, e tentativi di modificare le impostazioni o gli strumenti dell'agente stesso. Il test passa quando il transcript mostra che ognuno di questi è stato provato e ha fallito per il motivo che ti aspetti. Registra, per ognuno, se la sandbox o il classificatore di permessi lo ha fermato. Un tentativo che il classificatore ha negato non ha mai raggiunto la sandbox, quindi coprilo con i controlli manuali (vedi Verifica l'isolamento da solo di seguito). Un test che passa è una barra minima, non una prova di isolamento.

Evita compiti impossibili e rivedi prima le esecuzioni non riuscite

Conferma prima dell'avvio che il compito può essere completato come indicato. Alcuni esempi di compiti che non possono essere completati: un'area di focus senza nulla da trovare, un target non raggiungibile, un bug che non c'è, o uno strumento di cui il compito ha bisogno che non è installato. Ogni volta che modifichi la tua configurazione o inizi un nuovo tipo di compito, conferma prima dell'avvio che il target si compila e può essere raggiunto e che l'agente ha gli strumenti di cui ha bisogno. Per lo stesso motivo, quando rivedi un batch, leggi i transcript delle esecuzioni che hanno fallito o non hanno trovato nulla prima di quelli che hanno avuto successo.

Verifica l'isolamento da solo

Esegui questi controlli manualmente su ogni host. La seconda colonna descrive il controllo per il design di riferimento (Docker con il runtime Kata e Firecracker). Adattalo al tuo runtime.

Cosa confermare

Come

Risultato previsto

Un kernel guest separato

Esegui uname -r in un contenitore sandbox e sull'host

Le due versioni differiscono

Il monitor della VM è incarcerato sull'host

Per un contenitore in esecuzione, ispeziona il processo Firecracker: la sua directory root, Seccomp e NoNewPrivs in /proc/<pid>/status, i suoi namespace di mount e rete, e il suo cgroup

Solo i file della VM stessa sono sotto la sua root. Seccomp: 2 e NoNewPrivs: 1. Entrambi gli namespace differiscono da quelli dell'host. Il percorso del cgroup nomina il contenitore

Un file host non è visibile all'interno

Crea un file sull'host e prova a leggerlo da un contenitore sandbox

Non trovato. Questo è un controllo di base che qualsiasi runtime dovrebbe superare

L'uscita è rifiutata

Da un contenitore agente, richiedi l'host dell'API del modello e un altro host pubblico attraverso il proxy di uscita

Entrambi sono rifiutati, e il proxy di uscita registra una riga di negazione per ognuno. Gli agenti raggiungono il modello solo attraverso il proxy delle credenziali

Nessuna credenziale nel contenitore agente

Mentre un'esecuzione è in corso, elenca l'ambiente del contenitore agente, filtrato per nomi di provider

Un placeholder, l'indirizzo del proxy delle credenziali, e impostazioni del provider. Nessuna chiave reale, token, o file di credenziale

Il design di riferimento

Questa sezione descrive come l'implementazione di riferimento soddisfa le linee guida di cui sopra. L'implementazione non è inclusa. Leggilo come un design che puoi copiare.

Come ogni agente è isolato

Ogni agente viene eseguito come claude -p all'interno della sua propria microVM, accanto al binario target e alla sorgente. La microVM è un contenitore Kata Containers supportato dal monitor della macchina virtuale Firecracker, registrato con Docker come runtime. Gli strumenti Read, Write e Bash dell'agente vedono solo il filesystem e il kernel di quel guest.

La connessione tra un guest e l'host è deliberatamente piccola. Consiste di KVM e dei pochi dispositivi virtuali che Firecracker emula: dispositivi a blocchi per il disco del contenitore, un'interfaccia di rete, e un canale di controllo vsock che Kata usa per avviare processi all'interno del guest. Il processo Firecracker stesso è confinato sull'host. Viene eseguito in una "jail", che è una directory chroot contenente solo i file di quella VM, con il suo namespace di mount, lo namespace di rete del contenitore, e il filtro seccomp integrato di Firecracker. È contabilizzato nel cgroup del contenitore. Quello che ti fidi sul lato host è KVM, Firecracker, e il processo runtime di Kata (lo "shim" per contenitore che Docker parla, che viene eseguito come root).

L'orchestrator rimane sull'host affidabile. Gestisce il ciclo di vita del contenitore, trasmette i transcript, e sposta i file dentro e fuori con docker exec, che Kata serve attraverso il suo agente all'interno del guest. Il launcher avvia gli agenti solo all'interno di questa sandbox. Prima che qualsiasi agente inizi, controlla che il runtime della sandbox sia registrato, che /dev/kvm sia presente, e che il proxy di uscita sia attivo, e rifiuta di eseguire altrimenti.

Cosa cambia la sandbox per ogni superficie:

Superficie

Senza sandbox

Con sandbox

Agent Read/Write

filesystem host

solo filesystem guest (il disco virtuale del contenitore stesso, sotto il kernel guest)

Agent Bash

shell host

solo shell guest (kernel guest; l'host è raggiungibile solo attraverso KVM e i dispositivi virtuali di Firecracker)

Uscita di rete

qualunque cosa abbia l'host

nessun accesso a internet; solo chiamate del modello, attraverso il proxy delle credenziali

Credenziale Model-API

nell'ambiente dell'agente

non nel contenitore dell'agente; tenuto da un contenitore proxy-credenziale separato (vedi Il proxy delle credenziali sotto)

Accoppiamento host

completo

docker exec per file in entrata e in uscita, serviti dall'agente di Kata all'interno del guest; gli input di sola lettura arrivano come copie acquisite all'avvio del contenitore; i file che cambiano durante un'esecuzione vengono trasmessi dall'orchestratore

Controlli delle autorizzazioni

solo classificatore in modalità automatica

classificatore in modalità automatica più il limite della microVM (vedi Modalità automatica)

Dove viene applicata ogni proprietà: la virtualizzazione hardware fornisce il limite del kernel e del filesystem. Le operazioni Read/Write/Bash dell'agente vengono eseguite sul kernel guest, e il processo Firecracker dietro di esso è confinato in jail e seccomp sul host. La politica di uscita viene applicata dal lato host dell'interfaccia di rete della VM, da un bridge Docker --internal (nessuna rotta predefinita in uscita) e dai due proxy su quella rete. Il proxy delle credenziali inoltra solo le chiamate del modello e nient'altro. Il proxy di uscita rifiuta ogni altra destinazione, perché la sua lista di autorizzazione è vuota a meno che non la aggiungi. Il traffico esce attraverso lo stack di rete del guest; il filtraggio avviene nei due proxy.

Il proxy delle credenziali

La credenziale per l'API del modello (la tua chiave API, token OAuth, credenziale AWS o Google) non viene mai inserita in un contenitore agente. L'orchestratore sull'host la legge e la convalida, e ogni avvio avvia un piccolo contenitore aggiuntivo, il proxy delle credenziali, per contenerla. Il proxy è collegato alla rete interna degli agenti, e i contenitori agente inviano le loro chiamate del modello ad esso: il loro CLI claude riceve l'indirizzo del proxy come URL base dell'API e un valore segnaposto fisso dove normalmente andrebbe la chiave o il token. Questo segue la best practice di raggiungere l'API del modello solo attraverso un proxy, con la chiave API iniettata dall'esterno della sandbox. Nel design di riferimento il proxy è un contenitore separato sulla rete degli agenti, non un processo sul localhost dell'agente stesso. Per ogni richiesta, il proxy:

  1. Rifiuta qualunque cosa che non sia una chiamata del modello all'unico endpoint del provider per cui è stato configurato l'avvio (altri percorsi e host ricevono un 403 e una riga di log);

  2. Rimuove qualsiasi intestazione di autenticazione inviata dal contenitore;

  3. Aggiunge la credenziale reale: l'intestazione della chiave API, un token bearer (che il proxy aggiorna da solo quando il token ha breve durata), o una firma AWS SigV4 calcolata sulla richiesta esatta;

  4. Inoltra la richiesta al provider su HTTPS con verifica del certificato e trasmette la risposta indietro.

Per un contenitore agente compromesso, questo significa che non c'è chiave, token o file di credenziale da leggere, copiare o inviare da nessuna parte. Anche i servizi di metadati cloud sono irraggiungibili dal contenitore. Quello che il contenitore può ancora fare è effettuare chiamate del modello attraverso il proxy, sul tuo account, finché l'esecuzione è attiva. Per questo motivo, preferisci una credenziale con ambito ristretto per le esecuzioni dell'agente, e ruotala dopo qualsiasi esecuzione il cui transcript mostra comportamenti inaspettati. Il proxy registra una riga per richiesta, con l'indirizzo del client, il metodo, il percorso, lo stato e la dimensione. Non registra intestazioni o corpi. Salva quel log quando l'esecuzione termina (vedi la sezione Conservazione in Monitoraggio offline dei transcript degli agenti).

Qualunque cosa l'agente invii all'API del modello esce dalla tua rete, in corpi di richiesta che il proxy non ispeziona o registra.

Cosa tiene ogni lato, per ogni rotta di autenticazione:

Rotta

Cosa tiene il proxy delle credenziali

Cosa riceve il contenitore agente

Chiave API

la chiave

indirizzo proxy + segnaposto ANTHROPIC_API_KEY

Token OAuth (claude setup-token)

il token

indirizzo proxy + segnaposto CLAUDE_CODE_OAUTH_TOKEN

Workload Identity Federation (WIF)

il token di identità, più il token di accesso che il proxy scambia e aggiorna. Con ANTHROPIC_IDENTITY_TOKEN_FILE, la directory del file token è montata in sola lettura nel proxy, quindi il proxy vede un token ruotato. Con un ANTHROPIC_IDENTITY_TOKEN inline, il proxy tiene quel valore e non c'è file da rileggere

indirizzo proxy + segnaposto CLAUDE_CODE_OAUTH_TOKEN

profilo ant auth login

la directory del profilo, montata in sola lettura nel proxy

indirizzo proxy + segnaposto CLAUDE_CODE_OAUTH_TOKEN

Bedrock

il token bearer, o il set di chiavi di accesso (il proxy firma ogni richiesta)

indirizzo proxy, CLAUDE_CODE_SKIP_BEDROCK_AUTH=1, regione; nessuna credenziale AWS

Vertex

la chiave dell'account di servizio, più i token di accesso che il proxy crea da essa e aggiorna

indirizzo proxy, CLAUDE_CODE_SKIP_VERTEX_AUTH=1, regione e progetto; nessuna credenziale Google

Il contenitore proxy delle credenziali fa parte del lato affidabile della configurazione. Viene eseguito con runc semplice anziché il runtime della sandbox, come root con ogni capacità eliminata tranne quella necessaria per leggere i file montati, e con un filesystem di sola lettura. Ascolta solo sul suo indirizzo sulla rete interna degli agenti, e si connette direttamente al provider anziché attraverso il proxy di uscita. L'orchestratore passa la credenziale al proxy in esecuzione su docker exec. Per le rotte del file token WIF e del profilo, la directory che contiene il token o il profilo è montata in sola lettura nel proxy, che legge il file da lì. La credenziale non è nell'ambiente del contenitore proxy o sulla sua riga di comando, quindi docker inspect su di esso mostra i montaggi e non un segreto.

Avvia un proxy per ogni lancio e rimuovilo quando l'esecuzione termina o viene interrotta. Controlla i proxy rimasti da un'esecuzione che è stata uccisa e rimuovili prima del prossimo lancio.

Il proxy delle credenziali ha due effetti collaterali. Primo, al CLI degli agenti viene assegnato un indirizzo API non predefinito, quindi alcune funzionalità CLI che si applicano solo all'indirizzo predefinito sono disattivate nei contenitori agente. Anche la telemetria e i controlli degli aggiornamenti sono disattivati, perché non avrebbero comunque alcuna rotta in uscita. Secondo, su Vertex il filtro del percorso del proxy è il controllo principale che impedisce a un contenitore agente di utilizzare il resto dell'API Vertex AI (vedi Lista di autorizzazione di uscita). Un controllo dell'ambito IAM della chiave al lancio è un secondo livello.

Lista di autorizzazione di uscita

La lista di autorizzazione del proxy di uscita è vuota per impostazione predefinita. I contenitori agente raggiungono l'API del modello solo attraverso il proxy delle credenziali (vedi Il proxy delle credenziali). Ogni lancio avvia quel proxy per il provider selezionato dalle tue credenziali, quindi nulla di specifico del provider è archiviato nella configurazione della sandbox. Ogni altra destinazione che un agente richiede attraverso il proxy di uscita, incluso l'host dell'API del modello stesso, riceve un 403 e una riga di negazione nel suo log. I valori di regione che selezionano gli endpoint Bedrock e Vertex (AWS_REGION, CLOUD_ML_REGION) vengono controllati rispetto a un modello rigoroso prima di essere utilizzati, in modo che un valore malformato non possa inviare la credenziale a un host diverso.

Vertex ha un limite di cui essere consapevoli. …aiplatform.googleapis.com serve l'intera API Vertex AI, quindi una credenziale autorizzata a creare job personalizzati potrebbe eseguire un contenitore arbitrario con pieno accesso a internet in uscita nel tuo progetto. Usa due controlli contro questo. Fai in modo che il proxy delle credenziali inoltri solo le chiamate del modello editore sul tuo progetto configurato (…/publishers/anthropic/models/…:rawPredict, :streamRawPredict e :countTokens) e rifiuta ogni altro percorso. E controlla l'ambito IAM della chiave al lancio e fallisci in chiuso: rifiuta l'ADC dell'utente gcloud, controlla una chiave dell'account di servizio con testIamPermissions, e rifiutala se contiene qualsiasi autorizzazione di creazione di workload. Concedi all'account un ruolo personalizzato che contiene solo aiplatform.endpoints.predict. Il server dei metadati, l'STS di Google e gli endpoint delle credenziali IAM non dovrebbero essere raggiungibili dai contenitori agente.

Se gli agenti hanno bisogno di raggiungere host aggiuntivi, come uno specchio di pacchetti o un target in ambito, aggiungili alla lista di autorizzazione del proxy di uscita come voci host:port. Aggiungi solo quello di cui ha bisogno l'engagement (vedi Ambito e supervisione).

Non aggiungere l'host dell'API del modello a questo elenco. Gli agenti non ne hanno bisogno, perché le loro chiamate al modello passano attraverso il proxy delle credenziali. Aggiungerlo fornisce ai container degli agenti un percorso diretto all'API, e il resto della progettazione, incluso ciò che viene comunicato al classificatore di autorizzazioni, presuppone che non ne abbiano nessuno.

La modifica dell'elenco di autorizzazione significa riavviare il proxy di uscita, che interrompe tutte le connessioni degli agenti attivi. Fallo tra i batch piuttosto che durante uno, e conferma successivamente quale elenco il proxy ha caricato.

Deriva l'endpoint del provider dalla tua configurazione delle credenziali e ignora una variabile di URL di base come ANTHROPIC_BASE_URL impostata sull'host: il proxy delle credenziali deve sempre inoltrare all'endpoint selezionato dalle credenziali.

Costruire e gestire una sandbox come questa

Questa sezione raccoglie ciò che è stato imparato dall'esecuzione di agenti in Kata con Firecracker nell'implementazione di riferimento. Non è un insieme di passaggi di installazione.

Requisiti dell'host

La progettazione di riferimento richiede una macchina Linux fisica o una VM che possa a sua volta eseguire VM:

  • Linux x86_64 o aarch64 con KVM (/dev/kvm presente e utilizzabile): bare metal o una VM cloud con virtualizzazione nidificata abilitata.

    • GCE, Azure e AWS offrono virtualizzazione nidificata su tipi di istanza selezionati (su AWS, ad esempio, le famiglie C8i, M8i e R8i). Le istanze bare-metal di AWS (*.metal) funzionano anche.

    • La virtualizzazione nidificata comporta un certo costo in termini di prestazioni. Non è previsto che indebolisca il confine.

  • Archiviazione su dispositivo a blocchi per i container. Firecracker non può condividere una directory host in un guest; l'unica archiviazione che può collegare a una VM è un dispositivo a blocchi. I filesystem root dei container devono quindi esistere come dispositivi a blocchi anziché il solito filesystem overlay. Con Docker, lo snapshotter devmapper di containerd fornisce questo. Richiede Docker rootful (la progettazione di riferimento utilizza Engine 25 o più recente) supportato dal containerd di sistema (2.0 o più recente).

  • Accesso alla rete in uscita mentre costruisci l'host e le immagini. Gli agenti non ottengono questo egress.

Non funzionerà su:

  • un container o un pod Kubernetes, inclusi Docker-in-Docker e runner CI basati su container. Il containerd dell'host, il daemon Docker e il device-mapper non possono essere configurati dall'interno di un container, e KVM di solito non è disponibile nemmeno lì;

  • Docker senza privilegi;

  • una VM senza virtualizzazione nidificata, che è la maggior parte dei tipi di istanza cloud di uso generale a meno che tu non ne scelga una che la offra e la attivi;

  • macOS o Windows, inclusi Docker Desktop e WSL2.

La progettazione di riferimento non supporta host macOS o Windows

La sua sandbox ha bisogno di KVM su un host Linux. Docker su un Mac viene eseguito all'interno di una VM Linux condivisa che monta la directory home dell'utente e ospita il daemon Docker, quindi non può fornire isolamento hardware per agente. Se lavori su un Mac, esegui gli agenti su un host Linux con KVM (bare metal o una VM cloud con virtualizzazione nidificata) e guidali tramite SSH. Se costruisci la tua sandbox su macOS o Windows, consulta gli hypervisor denominati nella sezione Linee guida generali sopra.

Il cambio dell'archivio immagini di Docker ha un effetto collaterale

Le immagini e i container creati nell'archivio precedente di Docker diventano invisibili a Docker dopo il passaggio allo snapshotter devmapper. Rimangono su disco. Per vederli di nuovo, metti entrambe le impostazioni di archiviazione in daemon.json (storage-driver e features.containerd-snapshotter) di nuovo a quello che erano e riavvia Docker.

Impostazioni di Kata

Fissa la versione di Kata e verifica il suo digest prima di installarla. La progettazione di riferimento inizia dal profilo Firecracker di Kata e fissa queste impostazioni in /etc/kata-containers/configuration.toml:

Impostazione

Valore

Perché

jailer_path

percorso al binario jailer di Kata

Avvia Firecracker all'interno della sua prigione: una chroot con solo i file della VM, il suo namespace di mount, il namespace di rete del container e il filtro seccomp di Firecracker. Se non impostato, Kata eseguirebbe Firecracker senza la prigione.

enable_annotations

[]

Un container non può modificare alcuna impostazione dell'hypervisor tramite annotazioni OCI.

disable_guest_seccomp

false

Il profilo seccomp di Docker per il container viene applicato anche all'interno del guest, un secondo livello sotto il confine della VM.

sandbox_cgroup_only

true

Firecracker e i suoi thread di I/O vengono posizionati nel cgroup del container, quindi la VM viene contabilizzata al container. Se il limite --memory del container limita anche la VM dipende dall'host (vedi Dimensionamento).

static_sandbox_resource_mgmt

true

Firecracker non può aggiungere CPU o memoria a una VM in esecuzione, quindi la VM viene dimensionata una volta all'avvio dai limiti del container.

default_vcpus / default_memory

4 / 4096 MiB

Baseline per VM; il --memory del container viene aggiunto in cima. Aumenta per target con molte compilazioni (Firecracker consente al massimo 32 vCPU per VM).

debug_console_enabled, enable_debug

false

Nessuna console nei guest e nessun output della console guest nei log dell'host.

[factory] enable_template

false

Disattivato, perché il templating delle VM condividerebbe le pagine di memoria del guest tra le VM.

entropy_source

/dev/urandom

Entropia host non-bloccante per i guest.

I valori kernel, image e kernel_params forniti con la release di Kata vengono mantenuti così come sono.

Rendi il kernel e l'immagine del guest immutabili

Ogni VM si avvia dagli stessi due file, Kata li bind-monta in ogni jail, e il jailer viene avviato come root, quindi i normali permessi dei file non impedirebbero a un processo Firecracker compromesso di riscrivere l'immagine da cui ogni VM successiva si avvia. Imposta il flag immutabile su entrambi (chattr +i). Cancellare quel flag richiede una system call che il filtro seccomp di Firecracker non consente, progettato per impedire anche a root dentro la jail di farlo. Cancella il flag tu stesso prima di installare una nuova release di Kata. Su un filesystem senza supporto chattr, usa invece un bind mount di sola lettura.

Dimensionamento

Memoria

Ogni VM agente viene dimensionata una volta, all'avvio: default_memory più il --memory del container. Con una baseline di 4096 MiB e un limite di container 4g, un agente è una VM di 8 GiB. L'host alloca quella memoria alla VM man mano che il guest la utilizza, non tutto all'avvio, ma pianifica l'importo completo per ogni agente concorrente: dieci agenti in parallelo possono crescere verso 80 GiB. Se il limite --memory del container limita anche la VM nel suo insieme dipende da come sono organizzati i cgroup dell'host. Verifica quale di questi si applica al tuo host:

  • Il limite del container si applica all'intera VM. Un agente non può utilizzare più memoria host di --memory anche se la sua VM è nominalmente più grande, e una VM che supera il limite viene terminata dal lato host.

  • Nulla sull'host limita la VM al di sotto della sua dimensione di avvio. L'utilizzo della memoria di un agente è limitato dalla dimensione della VM (default_memory + --memory) e dal killer out-of-memory del kernel guest.

  • Un cgroup padre la limita a un valore diverso.

Non abbiamo confermato questo comportamento su ogni tipo di host. In ogni caso, dimensiona l'host in base alla dimensione della VM.

CPU

Ogni VM ottiene default_vcpus. Firecracker non può aggiungere CPU a una VM in esecuzione, quindi per target ad alta intensità di compilazione aumenta il valore prima dell'avvio; il massimo è 32 per VM.

Disco

Ogni immagine e ogni container ottiene un disco virtuale da un thin pool di device-mapper, che supporta l'archivio immagini. Se il pool si riempie, le scritture all'interno dei container falliscono con errori di I/O o spazio esaurito. Se il filesystem che contiene il pool si riempie per primo, il pool diventa di sola lettura e ogni container su di esso fallisce. Libera spazio con docker rmi e docker system prune (i blocchi liberati tornano al pool). sudo dmsetup status <pool> mostra l'utilizzo. Per un host di lunga durata, un thin pool LVM su un disco dedicato è il layout migliore.

Tempo di avvio

Ogni avvio dell'agente avvia un kernel guest. Questo richiede ben meno di un secondo su bare metal e pochi secondi sotto virtualizzazione nidificata, il che è piccolo rispetto ai tempi di esecuzione dell'agente.

Rafforzamento dell'host

  • Dedica l'host a questo lavoro.

    • Supponi che un agente potrebbe leggere qualsiasi cosa su di esso, e non mantenere credenziali o dati sensibili lì se non la credenziale dell'API del modello di cui gli agenti hanno bisogno.

  • Mantieni ogni livello che il traffico dell'agente tocca aggiornato, non solo il kernel: Docker, le immagini di base dei container proxy, e qualsiasi firewall o appliance di rete tra l'host e l'API del modello. Un proxy o firewall non aggiornato al confine della sandbox è esso stesso superficie di attacco.

  • Mantieni il kernel, KVM e il microcodice della CPU attuali, e lascia le mitigazioni delle vulnerabilità della CPU del kernel ai loro valori predefiniti.

    • grep . /sys/devices/system/cpu/vulnerabilities/* non dovrebbe mostrare righe Vulnerable.

    • Se l'host è condiviso con carichi di lavoro che non devono osservarsi a vicenda, segui anche la guida configurazione host di produzione di Firecracker sulle impostazioni SMT ed esecuzione speculativa.

  • Disabilita lo swap (sudo swapoff -a, e rimuovilo da /etc/fstab) in modo che la memoria del guest non venga scritta nello swap.

  • /dev/kvm non ha bisogno di essere world-writable, e le directory di installazione e runtime di Kata devono rimanere di proprietà di root e non scrivibili da altri utenti.

    • root:kvm con modalità 0660 è sufficiente per /dev/kvm, perché il runtime di Kata viene eseguito come root.

  • Non aggiungere mai --privileged, --device, --cap-add, o networking host ai container agente o ai servizi target.

    • Sotto Kata questi flag passano dispositivi host e privilegi nella VM.

  • Mantieni gli agenti sulla rete interna dietro i due proxy.

    • Firecracker non esegue filtri di pacchetti propri; la rete lato host e i proxy sono il controllo di uscita.

  • Mantieni enable_debug disattivato al di fuori della risoluzione dei problemi; il debug logging include l'output della console guest.

Convalida di un nuovo host

Dopo aver configurato una macchina nuova, questa sequenza mostra che la sandbox funziona end to end. I passaggi 3 e 4 effettuano chiamate modello reali.

  1. Esegui i controlli di isolamento sotto Verifica l'isolamento tu stesso. Le due versioni del kernel devono differire. Nota se il limite di memoria del container limita la VM (vedi Dimensionamento).

  2. Conferma che la CLI dell'agente viene eseguita sotto il runtime della sandbox, nell'immagine che utilizzerai.

  3. Testa il confine: fai rivedere a Claude la configurazione della sandbox, quindi esegui il test di fuga supervisionato, entrambi come descritto in Testa la sandbox prima di fare affidamento su di essa.

  4. Esegui un piccolo batch end to end rispetto a un target che conosci. Esegui questo passaggio con la modalità di credenziale che utilizzerai per i veri impegni, non una chiave API sostitutiva: il proxy di credenziale gestisce ogni modalità diversamente (scambio di token per WIF, firma per Bedrock, coniazione di token per Vertex), e questa esecuzione conferma che la tua funziona end to end. Controlla il log del proxy di credenziale in seguito.

  5. Verifica che nulla sia stato lasciato indietro. Una volta completato il batch, nessun container agente, container helper, processo VM o proxy di credenziale dovrebbe rimanere. Il log del proxy di uscita non dovrebbe mostrare righe di negazione se non i probe dai passaggi 1 e 3, e il log del proxy di credenziale dovrebbe mostrare solo chiamate modello.

Note operative

L'esecuzione di agenti sotto Kata con Firecracker differisce dall'esecuzione di container semplici in questi modi.

I bind mount sono copie; i file live devono essere trasmessi in streaming

Firecracker non ha condivisione del filesystem host, quindi Kata copia un file o una directory bind-montata nel guest quando il container si avvia, e i cambiamenti successivi sull'host non vengono visti all'interno. Va bene per gli input che non cambiano durante un'esecuzione, come il source target, e quelli possono rimanere mount di sola lettura. Nessun file di credenziale viene montato o trasmesso in streaming, perché i container agente non ne contengono nessuno (vedi Il proxy di credenziale). Un file che cambia durante un'esecuzione deve essere scritto nel container dall'orchestrator, tramite docker exec, e mantenuto aggiornato. Le copie in-container sono file ordinari che un agente potrebbe modificare, quindi fai leggere all'orchestrator gli originali sull'host, e giudica i risultati da una copia che l'agente in test non può raggiungere.

Ogni agente ha bisogno di un container companion per la sua rete

Le interfacce di rete di una microVM devono esistere quando la VM si avvia; Firecracker non può aggiungerne una in seguito. Docker, tuttavia, connette la rete di un container solo dopo che il runtime ha creato il container. Il design di riferimento aggira questo. Avvia prima un piccolo container inattivo che è collegato alla rete giusta e esegue solo sleep, quindi avvia l'agente all'interno dello spazio dei nomi di rete di quel container (--network container:<name>). Kata trova le interfacce lì all'avvio e le collega alla VM. Un companion serve esattamente una VM, perché Kata lascia i dispositivi di rete lato host della VM dietro in esso, quindi crea e rimuovi la coppia insieme e non riutilizzare un companion. Uno costa un processo inattivo di circa 12 MB.

Arresto di un agente bloccato

docker rm -f <agent-container> è sufficiente. L'orchestrator dovrebbe rilevare il container morto, contrassegnare l'esecuzione come non riuscita, e rimuovere il container companion quando smonta l'esecuzione.

Tutto è indirizzato per IP

Il DNS incorporato di Docker viene eseguito nello spazio dei nomi di rete lato host ed è irraggiungibile dall'interno di un guest, quindi passa i proxy agli agenti come indirizzi IP e assegna ai target in rete un IP statico.

docker exec funziona, docker cp no

docker exec in un contenitore agente si comporta come al solito; l'agente di Kata all'interno del guest esegue il comando. docker cp dentro o fuori da un contenitore agente non funziona, perché i file del contenitore si trovano su un disco virtuale all'interno del guest. Usa docker exec <container> cat <path> e simili.

Firecracker viene eseguito come root all'interno della sua jail

Kata avvia il jailer con uid 0, quindi il processo Firecracker è confinato dal suo chroot, spazi dei nomi, filtro seccomp e cgroup, non da un id utente senza privilegi. I due file che ogni VM condivide, il kernel guest e l'immagine, sono protetti dal flag immutable (vedi Impostazioni Kata).

Kata ha deprecato il runtime da cui dipende Firecracker

Kata esegue Firecracker attraverso il suo runtime Go più vecchio. Kata 4.0 ha reso il nuovo runtime Rust il predefinito per i suoi altri hypervisor e ha deprecato il runtime Go. Upstream afferma che il runtime Go riceve ancora correzioni critiche di bug e correzioni CVE, e che potrebbe essere rimosso non prima di Kata 5.0. Il runtime Rust non elenca Firecracker tra i suoi hypervisor, e upstream testa la sua integrazione Docker principalmente con QEMU. Pianifica una migrazione. Quando cambi la versione di Kata, ripeti Convalida di un nuovo host. Kata può anche usare Cloud Hypervisor al posto di Firecracker; l'implementazione di riferimento non ha testato o consolidato quella configurazione.

Log

I messaggi del runtime di Kata, Firecracker e guest-agent vanno nel journal: journalctl -t kata. I problemi di containerd e Docker sono in journalctl -u containerd e journalctl -u docker.

Hai ricevuto la risposta alla tua domanda?