Passa al contenuto principale

Il modello di sicurezza

Perché un segreto non entra mai in una sandbox, in un container o nell'ambiente di un agente.

Il motore si fida della configurazione e di niente di ciò che esegue. Un modello, un comando, un tool o un agente esterno può essere sbagliato o ostile. Un segreto che ne raggiunge uno è un segreto perso. Ogni regola qui sotto nasce da questo.

Il token​

Un repository privato si clona con il token nominato da Workspace.tokenEnv. Il token arriva solo al processo git sull'host, tramite il suo ambiente e GIT_ASKPASS. Non compare mai in un argv, in un URL del remoto scritto su disco, in un log, in un evento o in una sandbox.

Anche il push è un passo deterministico del motore sull'host. builtin:open_pr spinge il branch di integrazione con lo stesso GIT_ASKPASS, e la forge apre la pull request (vedi Git e pull request).

La sandbox​

Nessun comando generato da un agente gira fuori dalla sandbox Docker. Il container:

  • non ha rete per impostazione predefinita.
  • ha tutte le capability rimosse e no-new-privileges, con limiti di CPU, memoria e pids.
  • gira come utente non root.
  • monta /workspace come unico percorso scrivibile, e non monta mai il socket Docker.

Non riceve nessuna variabile d'ambiente e nessun segreto, tranne i nomi di variabile che un agente acp dichiara. L'adattatore Docker passa -e NAME e legge il valore dal proprio ambiente, così il valore non entra mai in un argv.

L'egress​

L'egress è una allowlist. Una sandbox senza sandbox.egress mantiene --network none. Con l'egress entra in una rete interna per ticket e raggiunge solo gli host elencati, attraverso un proxy squid attaccato al bridge predefinito.

Ogni altro host viene rifiutato, e così una connessione diretta che ignora il proxy. La sandbox, il proxy e la rete portano l'etichetta afe.ticket, e spariscono con il ticket (vedi Sandbox Docker).

La forge e gli agenti​

I token di git e della forge non entrano mai nei container. Il token arriva solo al processo git sull'host, tramite il suo ambiente e GIT_ASKPASS. Non compare mai in un argv, in un URL del remoto scritto in .git/config, in un log, in un evento o in un output restituito.

Il token della forge (un PAT GitHub fine-grained nominato da Workspace.tokenEnv) raggiunge l'API GitHub solo nell'header Authorization. Push, pull request e merge sono passi deterministici del motore sull'host. Gli agenti non ricevono mai gh, CLI di forge o token di forge, e un merge avviene solo dopo l'approvazione di una persona.

I percorsi dei tool​

.. e i percorsi assoluti vengono rifiutati. Ogni componente del percorso è aperto dalla radice del nodo con dir_fd e O_NOFOLLOW. Ogni symlink su un percorso viene rifiutato, anche uno che punta dentro la radice, o uno creato dentro la sandbox mentre una chiamata è in corso.

La sessione del browser​

POST /auth/login confronta il token con hmac.compare_digest, e imposta un cookie di sessione firmato con una chiave derivata dal token. Il cookie è HttpOnly, SameSite=Strict, Path=/, e Secure dietro HTTPS. Niente è tenuto lato server, un nuovo token termina ogni sessione, e il cookie non arriva mai in un log.

L'handshake di /rpc accetta il cookie solo quando l'Origin della richiesta è quello del server. La CLI continua a usare il bearer token (vedi Web UI).

Operations​

/livez, /readyz e /metrics non chiedono nessun token, quindi si legano a 127.0.0.1 a meno che --ops-host dica altro. La readiness nomina la dipendenza che fallisce, mai il suo testo di errore. Nessuna etichetta di metrica porta un id di ticket, un input o un segreto.

I valori degli header OTLP finiscono solo nella richiesta, mai in uno span, in un errore o in un log.

I segreti​

Nessun segreto è scritto in un manifest, in un log, in un evento o in una metrica. Un manifest nomina la variabile d'ambiente che lo contiene (apiKeyEnv, tokenEnv). Le stringhe di connessione sono lette all'avvio e mai ripetute. I valori che sembrano segreti vengono tolti dalla memoria e redatti dagli errori.

Vedi anche​