Se lasci che un agente IA esegua codice su infrastruttura condivisa, hai già perso. Questa è la conclusione scomoda a cui siamo arrivati dopo un anno di gestione di carichi di lavoro IA in produzione presso CodeCourier. Il modello non è malevolo; gli input lo sono. Prompt injection, avvelenamento della supply chain, processi fuori controllo, e cache silenziosamente corrotte troveranno ogni fessura in un ambiente non isolato. L'unica risposta credibile è una sandbox per agenti IA: una macchina Linux nuova, isolata a livello hardware, che si avvia in meno di un secondo, accetta le istruzioni dell'agente, ed è distrutta nel momento in cui l'esecuzione termina.
Questo articolo è il pilastro tecnico che abbiamo promesso. Copre il modello di minaccia, il confronto tra container, microVM, e VM complete, come provisioniamo microVM Firecracker supportate da E2B in meno di un secondo, come manteniamo stretti i filesystem e le reti, come i segreti non persistono mai, come registriamo ogni azione per l'audit, e le sette lezioni concrete che abbiamo imparato a nostre spese. Se stai costruendo agenti che toccano codice, questa è la domanda sul substrato che decide se puoi dormire tranquillo il venerdì sera.
Perché le sandbox non sono negoziabili per gli ingegneri IA
Una sandbox per agenti IA è un ambiente di esecuzione effimero e isolato - tipicamente una VM o microVM effimera - che un agente autonomo usa per eseguire codice, comandi, e strumenti senza accesso alle risorse dell'host, ad altri tenant, o a stato persistente. È la differenza tra un agente che redige una pull request e un agente che spedisce una CVE nella tua supply chain.
Tre proprietà rendono una sandbox una sandbox, non solo un container con buone intenzioni:
- Isolamento hardware. Il confine è applicato dall'hypervisor, non dai namespace del kernel accanto a cui gira. Un escape dal container diventa un escape dalla microVM - ordini di grandezza più difficile.
- Effimerità. Lo stato di disco, RAM, e rete svanisce quando l'esecuzione termina. Nessuna cache, nessun socket rimasto, nessun file temporaneo con token bearer.
- Provisioning in meno di un secondo. Se l'avvio a freddo è lento, gli ingegneri lo aggirano, condividendo sandbox tra esecuzioni. Nell'istante in cui accade, l'isolamento è sparito.
Salta una delle tre e non hai una sandbox. Hai un container con un budget di marketing.
Il modello di minaccia - cosa va storto senza isolamento
Ogni team con cui parlo sottovaluta la superficie di attacco di un agente autonomo. Il modello è non deterministico, gli input sono controllati dall'attaccante, e gli strumenti sono potenti per progetto. Ecco il catalogo delle minacce contro cui abbiamo costruito la nostra architettura.
1. Fallimento del contenimento del prompt injection
Un ticket di issue, un README, un commento in una dipendenza - qualsiasi testo che l'agente ingerisce è un'istruzione che potrebbe seguire. Abbiamo visto agenti convinti a fare git push verso un remote controllato da un attaccante, esfiltrare file .env tramite un one-liner curl, o installare un pacchetto il cui script post-installazione scrive in ~/.ssh/authorized_keys. Una sandbox non ferma il prompt injection. Contiene il raggio d'impatto a un disco che verrà distrutto in quindici minuti.
2. Avvelenamento della supply chain
Ogni npm install esegue codice arbitrario. Anche ogni pip install. Un pacchetto con typosquatting, un maintainer compromesso, un hook post-installazione malevolo - il tuo agente li eseguirà tutti allegramente. Senza sandbox, l'host riceve la backdoor. Con una sandbox, la riceve la VM usa e getta, e a nessuno importa.
3. Esfiltrazione via DNS, HTTP, o git
Un canale di esfiltrazione determinato è a un solo curl -d @secrets.txt di distanza. Su un host condiviso, quel traffico si mescola con il traffico legittimo. In una sandbox con un'allowlist di uscita che nega per default, la richiesta fallisce e la registriamo.
4. Processi fuori controllo ed esaurimento delle risorse
Un agente che riprova un test instabile in un ciclo while true divorerà ogni ciclo CPU che riesce a raggiungere. Senza quote per VM, una singola esecuzione cattiva abbatte l'host e tutti su di esso. Con le quote, la VM raggiunge il suo tetto, l'agente riceve il segnale OOM, e il resto della piattaforma non se ne accorge mai.
5. Perdita di dati tra tenant
Se due clienti condividono un processo, un kernel, o anche solo un filesystem, hai costruito un canale laterale. Attacchi di esecuzione speculativa, attraversamento di /proc, directory temporanee condivise - la storia della sicurezza multi-tenant è la storia della scoperta di nuove varianti di questo bug. Una microVM con il proprio kernel elimina la categoria.
Container vs microVM vs VM completa - il confronto che conta
Mi viene chiesto continuamente perché non abbiamo semplicemente usato Docker. Ecco la tabella che rimando indietro.
| Proprietà | Container (Docker) | microVM (Firecracker / E2B) | VM completa (KVM, EC2) |
|---|---|---|---|
| Confine di isolamento | Namespace del kernel, cgroups | Hypervisor, kernel dedicato | Hypervisor, kernel dedicato |
| Avvio a freddo | 100 ms - 2 s | 150 ms - 400 ms | 20 s - 90 s |
| Overhead di memoria | ~5 MB | ~5 MB | 100 - 500 MB |
| Densità per host | Centinaia | Migliaia | Decine |
| Resistenza a exploit del kernel | Bassa - kernel condiviso | Alta - kernel separato per VM | Alta - kernel separato per VM |
| Isolamento del filesystem | A livelli, spesso livelli condivisi | Block device per VM | Block device per VM |
| Adattabilità per codice non fidato | Rischioso | Progettato per questo | Sì, ma lento |
I container vincono su tooling ed ecosistema. Le VM complete non vincono nulla per il nostro caso d'uso - sono troppo lente da provisionare per richiesta. Le microVM Firecracker colpiscono l'unico punto della curva che conta per gli agenti IA: isolamento di livello hardware a velocità di avvio di livello container. Questo è il motivo tecnico per cui E2B esiste e il motivo per cui ci abbiamo puntato.
Come CodeCourier provisiona sandbox in meno di un secondo
L'architettura è costruita attorno a quattro primitive: un pool preriscaldato, il ripristino da snapshot, immagini template, e uno strato di orchestrazione sottile tra il nostro control plane e l'API E2B. Ecco il percorso che una sandbox segue dalla richiesta alla disponibilità.
- La richiesta atterra sul gestore sandbox. Il runner del workflow richiede una sandbox con un template (es.
node20-postgres), una regione, una forma CPU/RAM, e una policy di uscita. - Ricerca nel pool. Manteniamo un pool caldo di microVM in pausa per template per regione. Se esiste una corrispondenza, saltiamo completamente l'avvio.
- Ripristino da snapshot. Una VM corrispondente viene ripresa da uno snapshot di memoria in circa 120-180 ms. Il kernel, il gestore pacchetti, e il runtime del linguaggio sono già in RAM.
- Percorso a freddo. Se il pool è vuoto, avviamo una microVM nuova dall'immagine template di base. Firecracker segnala pronto in 150-250 ms; il tempo totale incluso il nostro overhead di orchestrazione si attesta a 300-600 ms.
- Iniezione di segreti e policy. Credenziali per passaggio di breve durata vengono consegnate all'agente tramite un canale di init solo in memoria. Le regole di uscita vengono applicate nel namespace di rete dell'host prima che l'agente esegua il suo primo comando.
- Consegna dell'handle al workflow. L'orchestratore restituisce un ID sandbox opaco. L'agente inizia a lavorare.
Mediana end-to-end, misurata sugli ultimi 30 giorni di produzione: 520 ms. p99: 1,4 s. Percorso a freddo (nessun hit del pool): 1,8 s p50. Questo è il numero che permette alla dashboard rivolta all'utente di dire "avvio sandbox" senza mostrare uno spinner.
Un estratto rappresentativo dal nostro orchestratore (TypeScript, semplificato):
import { Sandbox } from 'e2b';
async function provision(opts: {
template: string;
region: 'us-east' | 'eu-west';
egressAllowlist: string[];
stepSecrets: Record<string, string>;
}) {
const warm = await pool.tryClaim(opts.template, opts.region);
const sbx = warm ?? await Sandbox.create(opts.template, {
region: opts.region,
timeoutMs: 15 * 60 * 1000,
});
await applyEgressPolicy(sbx.id, opts.egressAllowlist);
await injectSecrets(sbx.id, opts.stepSecrets); // memory-only
return sbx;
}
L'intero macchinario - dimensionamento del pool, eviction, generazioni di snapshot, failover di regione - vive dietro quella superficie. Vedi come gestiamo le sandbox per la vista lato prodotto.
Isolamento di filesystem e rete in pratica
L'isolamento è una proprietà che devi applicare a ogni strato o non ne hai nessuna. Trattiamo il filesystem e la rete come le due porte blindate principali.
Filesystem. Ogni sandbox ottiene il proprio block device supportato da una copia dell'immagine template. Non c'è overlay condiviso con l'host. L'agente ha root dentro la VM ed esattamente nulla fuori. Le scritture non persistono tra le esecuzioni a meno che il workflow non spinga esplicitamente artefatti verso object storage o git. Quando l'esecuzione termina, il block device viene cancellato prima che lo slot torni al pool.
Rete. La policy predefinita è negare tutta l'uscita con un'allowlist curata: l'host git del cliente, i registri di pacchetti comuni (npmjs.org, pypi.org, crates.io), e l'endpoint LLM. Tutto il resto viene scartato al firewall dell'host. I clienti possono estendere l'allowlist per progetto, ma mai per esecuzione, e mai tramite l'agente stesso - questo permetterebbe al prompt injection di riscrivere i propri muri.
Il DNS viene risolto tramite il nostro resolver proprietario che registra ogni lookup. Un numero sorprendente di tentativi di esfiltrazione appare come query DNS verso domini di proprietà dell'attaccante molto prima che scatti qualsiasi richiesta HTTP. Li catturiamo lì.
Gestione dei segreti - mai far trapelare, mai persistere
Ogni bug sui segreti che abbiamo mai spedito veniva da un segreto che è vissuto più a lungo del necessario. La nostra regola è: di breve durata, con ambito ristretto, mai su disco, mai nei log. Nello specifico:
- Token per passaggio, non per esecuzione. Un workflow con dodici passaggi coniano dodici credenziali distinte, ciascuna valida per la durata di quel passaggio più una piccola finestra di grazia.
- Iniezione solo in memoria. I segreti passano attraverso un file env supportato da tmpfs che viene smontato all'uscita del processo. Non toccano mai lo storage persistente.
- Pulizia dei log a livello di streaming. Stdout e stderr passano attraverso un redattore prima di raggiungere il nostro database, la dashboard, o qualsiasi occhio umano.
- Nessun archivio di segreti leggibile dall'agente. L'agente non può enumerare i segreti disponibili. Può usare solo quelli che il workflow ha esplicitamente associato al passaggio corrente.
- Revoca automatica in caso di anomalia. Se la nostra pipeline di audit vede una credenziale usata fuori dal suo ambito dichiarato, viene revocata entro pochi secondi.
La conformità documenta questo in dettaglio - vedi le nostre pagine SOC 2 e GDPR - ma la sostanza ingegneristica sono i cinque punti sopra.
Osservabilità - registrare ogni azione dell'agente per l'audit
Un agente autonomo senza un registratore è una responsabilità. Trasmettiamo ogni evento significativo fuori dalla sandbox in tempo reale e lo persistiamo in storage immutabile:
- Ogni comando eseguito, con argomenti, directory di lavoro, codice di uscita, e durata.
- Ogni file scritto o letto sopra una soglia di dimensione configurabile, con un hash del contenuto.
- Ogni connessione di rete in uscita, l'IP risolto, la porta di destinazione, e il numero di byte trasferiti.
- Ogni chiamata LLM effettuata dall'interno della sandbox, incluso il modello, i conteggi dei token, e le chiamate a strumenti emesse dal modello.
- Ogni evento di materializzazione di segreti, ripulito dal valore del segreto stesso.
Il risultato è una timeline forense che puoi rivedere nella nostra dashboard o incanalare nel tuo SIEM. Quando un team di sicurezza aziendale chiede "cosa ha fatto davvero l'agente alle 14:32 del 4 marzo?", rispondiamo in secondi, non giorni. La stessa pipeline alimenta il nostro red-team notturno - vedi la panoramica sulla sicurezza per la configurazione avversariale.
Lezioni da un anno di IA nelle sandbox
Leggere dell'isolamento è una cosa. Gestirlo su carichi di lavoro reali è un'altra. Ecco le sette lezioni per cui abbiamo davvero pagato, con i numeri allegati.
Lezione 1 - le cache condivise sono un incidente di sicurezza in attesa di accadere
Il nostro primo prototipo condivideva una cache npm tra le sandbox per risparmiare 8-12 secondi sulle installazioni. Funzionava splendidamente finché un agente non ha installato un pacchetto con typosquatting il cui script post-installazione ha scritto una backdoor nella directory della cache. Le successive venti esecuzioni l'hanno raccolta. Abbiamo rimosso la cache condivisa lo stesso giorno. La correzione è stata cuocere i primi 200 pacchetti nell'immagine template - questo ha recuperato la maggior parte dell'accelerazione senza il rischio di stato condiviso.
Lezione 2 - i pool preriscaldati battono gli avvii a freddo ottimizzati
Abbiamo passato due settimane a raschiare 80 ms dal percorso a freddo di Firecracker. Poi abbiamo costruito un pool caldo e recuperato 280 ms gratis a ogni hit di cache. Lezione: non ottimizzare il percorso lento prima di averlo eliminato. Oggi, l'87% dei nostri provisioning di sandbox colpisce il pool. Il tempo mediano di provisioning è sceso da 1,4 s a 520 ms in una settimana.
Lezione 3 - i token di lunga durata sono un autogol
Usavamo coniare un singolo token git-push per esecuzione di workflow, valido per l'intera esecuzione. Era comodo. Era anche a un solo prompt injection dal disastro. Abbiamo ricostruito lo strato delle credenziali per coniare token per passaggio con un TTL di 60 secondi più una stretta di mano di rinnovo esplicita. La nostra finestra di esposizione delle credenziali nel caso peggiore è scesa da 40 minuti a meno di 2.
Lezione 4 - l'osservabilità si ripaga da sola alla terza settimana
La prima volta che un cliente ha chiesto perché il suo workflow avesse impiegato 14 minuti in più del solito, abbiamo rivisto la timeline, trovato un npm install instabile che riprovava contro un mirror lento, e corretto il template lo stesso pomeriggio. Quel singolo incidente ha giustificato l'intero stack di osservabilità. Tre mesi dopo, usiamo quelle timeline più come strumento di debug che di sicurezza.
Lezione 5 - lo scheduling equo ferma i vicini rumorosi
Un cliente ha eseguito un workflow che generava 100 suite di test parallele in una singola sandbox. La sandbox andava bene - ma il budget I/O dell'host no. Dopo aver aggiunto quote I/O per sandbox e limiti di concorrenza per tenant con uno scheduler a quote eque, la latenza p99 per tutti gli altri è scesa del 38% e non abbiamo mai più visto il problema.
Lezione 6 - gli snapshot sono una feature di fase uno, non di fase due
Abbiamo trattato gli snapshot delle sandbox come un piacevole extra per i primi sei mesi. I clienti che eseguivano workflow di più ore incontravano limiti di frequenza, interruzioni transitorie del modello, o test instabili e dovevano ricominciare da zero ogni volta. Quando abbiamo spedito lo snapshotting, il costo medio di un'esecuzione riuscita è sceso del 23% e i ticket segnalati dai clienti "il workflow è morto senza motivo" sono scesi a zero in due settimane.
Lezione 7 - il log di audit è il prodotto
Ogni ciclo di vendita enterprise alla fine raggiunge la domanda "dimostra che l'agente ha fatto esattamente ciò che afferma di aver fatto". Pensavamo che la risposta fosse il risultato. La risposta è la timeline. Tratta il tuo log di audit come un'interfaccia utente di prima classe, non un artefatto di conformità. La nostra velocità di chiusura degli affari è circa raddoppiata dopo aver spedito la vista timeline nella nostra dashboard.
Quando NON usare le sandbox
Non sono dogmatico su questo. Esistono casi reali dove una sandbox è eccessiva o persino controproducente:
- Pura inferenza, nessun uso di strumenti. Se l'agente legge solo da un'API e scrive un riassunto Markdown, non hai bisogno di una microVM. Hai bisogno di una funzione stateless.
- UX interattiva altamente sensibile alla latenza dove controlli ogni input. Un modello di completamento del codice in esecuzione sulla macchina propria di uno sviluppatore, senza input non fidato nel ciclo, è il proprio confine di fiducia.
- Plugin IDE profondamente integrati. Se l'agente per definizione agisce come lo sviluppatore, metterlo in sandbox rispetto al repo dello sviluppatore vanifica lo scopo. Metti in sandbox la rete, non il filesystem.
La linea che tracciamo in CodeCourier: qualsiasi agente che esegue codice per conto di un utente diverso da se stesso gira in una sandbox. Tutto il resto è caso per caso. Se stai usando Issue Sessions, Persona, o il Workflow Builder, sei dal lato sandbox della linea.
FAQ - sandbox per agenti IA
Che cos'è una sandbox per agenti IA?
Una sandbox per agenti IA è un ambiente di esecuzione effimero e isolato a livello hardware - di solito una microVM - che un agente autonomo usa per eseguire codice, installare pacchetti, eseguire comandi, e usare strumenti. Viene distrutta quando l'esecuzione termina, così nulla di ciò che fa l'agente persiste a meno che il workflow non lo esporti esplicitamente.
Perché una microVM è migliore di un container Docker per gli agenti IA?
Un container Docker condivide il kernel dell'host. Un exploit del kernel, una capability configurata male, o un escape dal namespace danno a un attaccante l'host. Una microVM esegue il proprio kernel sotto un hypervisor; un escape richiede di violare l'hypervisor, un bersaglio molto più difficile. Per codice non fidato - e tutto il codice generato da LLM è, per definizione, non fidato - le microVM sono la scelta prudente.
Come raggiunge E2B l'avvio di sandbox in meno di un secondo?
E2B usa microVM Firecracker, che si avviano in 100-250 ms perché eliminano ogni dispositivo, routine BIOS, e modulo del kernel di cui un carico di lavoro serverless non ha bisogno. Sopra a questo, manteniamo un pool preriscaldato di VM in pausa per ogni template. Un hit del pool si ripristina da uno snapshot di memoria in circa 120-180 ms.
Il prompt injection può evadere da una sandbox?
Il prompt injection non può violare il confine della sandbox stesso - questo è applicato dall'hypervisor, non dal modello. Ciò che il prompt injection può fare è convincere l'agente ad abusare delle risorse che possiede legittimamente dentro la sandbox: esfiltrare tramite un endpoint in allowlist, fare push verso il remote git sbagliato, o bruciare credito. La difesa è a strati: allowlist di uscita rigide, credenziali per passaggio con ambiti ristretti, e osservabilità che segnala le chiamate a strumenti anomale in tempo reale.
Quanto vive una sandbox?
Per impostazione predefinita, quindici minuti di inattività prima della distruzione automatica, con un massimo assoluto configurabile per workflow. I workflow lunghi usano il nostro protocollo di snapshot per mettere in pausa e riprendere lungo la durata di una singola esecuzione.
Dove vanno gli artefatti dei clienti dopo che la sandbox viene distrutta?
Ovunque il workflow li metta esplicitamente. I branch fanno push verso il tuo host git. Gli artefatti vengono caricati nel tuo object storage. Nient'altro sopravvive. Il block device viene cancellato prima che lo slot torni al pool.
La sandbox per agenti IA è conforme a SOC 2 e GDPR?
Sì. CodeCourier è SOC 2 Type II e gestisce un data plane esclusivamente UE per i carichi di lavoro sensibili al GDPR. Vedi SOC 2 e GDPR per i controlli completi.
Dove posso saperne di più?
Inizia con le nostre guide, sfoglia il blog di ingegneria, o leggi del team. Se vuoi parlarci di un carico di lavoro specifico, contattaci.