Gå til innholdet

Tillatelsesregler — én policy for hver muterende handling

Agenter i Control Center kan slette filer, pushe grener, publisere pull requests og kalle eksterne API-er. Hver av disse er en annen type risiko, og lenge var det bare én av dem — shell-kommandoer — som hadde en policy. Tillatelsesreglene finnes for å svare på ett spørsmål på samme måte, for hver muterende handling en agent kan utføre, uansett hvilken kjøretid eller hvilket verktøy som foreslår den: er dette tillatt, trenger det en godkjenning, eller blir det avslått?

Det finnes nøyaktig én policymotor. Den blir spurt på hvert punkt der en handling kan forlate systemet: verktøyregisteret til den innebygde harnessen, porten i MCP-dispatchseren på serversiden og mutasjoner fra repo-operasjoner. En regel som skrives én gang, gjelder derfor både for den innebygde kjøretiden og for eksterne agent-CLI-er — det finnes ingen andre, stillere vei rundt den. Den eldre kommando-policyen som bare gjaldt bash, fungerer fortsatt: en regel kan treffe et kommandoprefiks i stedet for en handlingsklasse, og begge formene lever side om side i samme lager.

Motoren er likevel ikke en erstatning for OS-sandkassen, og sandkassen er ikke en erstatning for den. De svarer på ulike spørsmål: tillatelsesreglene avgjør om et kall Control Center kan se, i det hele tatt får skje, mens sandkassen begrenser hvor den resulterende prosessen kan nå. cc_server legger på sandkassen der verten tilbyr en backend — men Windows tilbyr ingen, og Linux trenger bwrap og socat. På slike verter er tillatelsesreglene det ytterste håndhevelseslaget i stedet for en policy som ligger oppå et gulv, og det er verdt å vite når du bestemmer hvor romslig du vil være.

Hvert muterende verktøy erklærer hvilke ActionClasses det hører til, fra et lukket sett på tretten effektklasser. Fem av dem spør med én gang; resten tillater, og en regel er det som endrer det.

Klasse Innebygd standard Hva den dekker
fileDelete prompt Slette en fil (en slettelignende skriving, rm)
gitPush prompt Pushe til en git-remote
prCreate prompt Opprette en pull request
prPublish prompt Publisere en gjennomgang, slå sammen en PR
vendorSyncWrite prompt Skrive til et eksternt oppfølgingssystem (Linear, Jira, GitHub-synk)
fileWriteOutsideWorktree allow Skrive en fil utenfor den isolerte worktreen
gitCommit allow Opprette en git-commit
networkEgress allow Nettverkstrafikk ut (netthenting, vilkårlig HTTP)
secretAccess allow Lese en hemmelighet eller påloggingsdetaljer
packageInstall allow Installere en pakke (npm, pip, pub, brew)
processSpawn allow Starte en prosess (shell og alt som starter en shell)
workspaceMutation allow Endre strukturen i arbeidsområdet (repoer, områder, agenter)
enclosureControl allow Styre et isolert miljø (stasjon): starte en VM, sende den input

De åtte klassene som tillater som standard, ble valgt ut fra en antagelse om at sandkassegulvet gjelder under dem. Det gjør det der verten tilbyr en backend, og det gjør det ikke på Windows eller på en Linux-boks som mangler bwrap og socat — så hvis du vil at fileWriteOutsideWorktree eller packageInstall skal styres av en regel der, er det en regel du må skrive selv.

Settet er lukket med vilje. Et nytt muterende verktøy som ikke erklærer noen klasse, feiler ratchet-testen, så taksonomien kan bare vokse gjennom en uttrykkelig, begrunnet beslutning — «villvekst i taksonomien er døden for denne funksjonen». Tretten klasser er nok til å uttrykke de policyene folk faktisk skriver (aldri push uten å spørre, aldri slett utenfor en worktree, alltid tillat lesing), og få nok til at innstillingsgrensesnittet fortsatt er forståelig.

En regel avbilder (scope, ActionClass | command prefix) → allow | prompt | deny. Omfangene ligger i lag fra mest til minst spesifikt:

område > agent > arbeidsområde > modusforhåndsvalg > innebygd standard

Oppslaget går etter spesifisitet først: det første omfanget med en regel som passer, bestemmer, og oppslaget stopper der. Mest restriktiv er bare en skilleavgjørelse — mellom to like spesifikke regler i samme omfang og når de flere klassene en enkelt handling erklærer, kombineres. Innenfor et omfang treffer en kommandoregel på det lengste kommandoprefikset. allow slår ikke deny noe sted.

To avgjørelser har harde garantier:

  • Fail-closed ved forespørsler. En prompt uten en tilkoblet godkjenner løses opp til avslått. Et ubesvart spørsmål er aldri et ja.
  • Mest restriktiv kombinasjon. En handling som spenner over flere klasser, kombinerer dem mest restriktivt; når flere klasser spør, lister én bekreftelse opp dem alle.

Det finnes med vilje ingen lås per runde. Hvert verktøykall løser opp policyen på nytt fra bunnen av, så gjentatt spørring for den samme handlingen begrenses av operatørens egen «Godkjenn i 8 timer», ikke av noe som er knyttet til en runde.

En regel kan begrense ARGUMENTENE til en handling, ikke bare verbet. «Kan pushe» og «kan pushe til feature/*» er forskjellige påstander, og bare den andre er en kontroll — en kapabilitetsport som bare autoriserer verbet, er formen bak de fleste publiserte agenthendelser.

En begrensning kan navngi:

  • stier — glob-mønstre (repos/**, !**/.env)
  • refs — git-refs, med !-negasjon (['**', '!main'] leses som «hvilken som helst gren unntatt main»)
  • verter — nettverksmål, med jokertegn for underdomener (*.internal)
  • kommandoer — kommandoprefikser, matchet på en ordgrense
  • tak — maxCount / maxCents, slik at «slett opptil 50 filer» lar seg uttrykke

Tre egenskaper følger av å holde grammatikken lukket og uten løkker, og alle tre er poenget: hver regel kan leses tilbake som en setning, hvert avslag kan navngi begrensningen som traff, og hele policyen kan listes opp — du kan se hva en agent får gjøre før den kjører.

Tre regler som betyr noe:

  • En begrenset regel er mer spesifikk enn en ubegrenset i samme omfang, så «nekt push til main» slår «tillat push» uten at noen trenger å tenke på rekkefølgen.
  • En restriktiv regel (deny / prompt) gjelder når forespørselen berører noen verdi den navngir; en permissiv regel (allow) gjelder bare når forespørselen er helt innenfor den. Å lese begge på samme måte ville la en agent hvitvaske en forbudt sti ved å pakke en uskyldig en ved siden av.
  • En regel som navngir et aspekt forespørselen ikke sier noe om, blir verken brukt eller hoppet over: den eskalerer til en godkjenning. Å hoppe stille over ville gjøre hver regel for beskyttede grener virkningsløs mot et verktøy som ikke rapporterer refen sin; å nekte stille ville avslå hver push uttrekkeren ikke kan beskrive. Uten en tilkoblet godkjenner gjør den eksisterende fail-closed-regelen denne eskaleringen om til et avslag.

En commandPrefix-regel matcher på en ordgrense: git push dekker git push origin main og ikke git pushx. Den normaliserer ikke shellen. git push (to mellomrom), cd sub && git push og GIT_DIR=… git push er alle forskjellige strenger, og ingen av dem matcher en regel om git push.

Det er en reell grense, og den sies som den er i stedet for å feies under teppet: kommandoregler er en bekvemmelighet for operatøren for å forme vanlig agentatferd, ikke en grense mot en fiendsk en. Grensene er effektklassene (som et verktøy erklærer og ikke kan skrive om), kommandonettet i modusen under policylageret, og OS-sandkassen under begge. En kommandoregel som løses opp til allow, løsner aldri noen av dem — modusnettet kjører etterpå, og deny er endelig.

Å svare på en forespørsel med «Godkjenn i 8 timer» skriver en ekte policyregel: avgrenset til et omfang (område / agent / arbeidsområde), bundet til argumentene (å godkjenne en push til feature/login gir feature/**, ikke main) og opphever seg selv etter en uttrykkelig TTL. Å si ja for de neste timene er ikke det samme som å stille skrive om den varige policyen din, og reglene den skriver, havner i samme lager med opphavet remembered og en utløpstid, slik at de kan trekkes tilbake tidlig.

Hver regel har ett:

  • advisory — tillat, men registrer at regelen traff. Dette er innføringsveien: rull ut en streng regel i advisory-modus, les revisjonssporet i en uke for å se nøyaktig hva den ville ha blokkert, og fremm den så. Uten dette nivået blir strenge policyer aldri slått på.
  • soft — nekt, men kan overstyres av noen som har overstyringsrettigheten, med en registrert begrunnelse. Overstyringen er i seg selv en revidert hendelse.
  • hard (standard) — nekt. Ingenting overstyrer den.

Den som drifter en installasjon, kan låse fast en policy som ingen arbeidsområdeadministrator kan løsne. Forvaltede regler ligger på serversiden og slås sammen mest restriktivt med hvert arbeidsområdes egen kjede — de er ikke et omfang på toppen av den, for en forvaltet allow øverst i kjeden ville la installasjonen overstyre et nekt fra et arbeidsområde, det motsatte av hensikten med en innstramming. En forvaltet regel kan derfor bare stramme til.

Å sette CC_SERVER_MANAGED_POLICY til en JSON-fil overstyrer de lagrede reglene helt, og det er dette som lar en operatør låse fast en holdning som ingen admin-grensesnitt kan vippe — svaret på «kan jeg hindre utviklerne mine i å slå av sikkerhetskontrollene?».

Autonomivriden er en profil, ikke et parallelt system

Seksjon med tittelen «Autonomivriden er en profil, ikke et parallelt system»

Autonomivriden per område er en navngitt profil over det samme policylageret, ikke en andre mekanisme. De tre innstillingene lagres og sendes som proposeOnly, actWithApproval og actFreely (formene med bindestrek er bare prosa i grensesnittet, og autonomy.setForSpace avviser alt annet). Å la den stå usatt oppfører seg som actWithApproval.

Hva hver av dem gjør med en avgjørelse etter oppslaget:

  • proposeOnly avslår hvert verktøy bak porten tvert. Agenten kan fortsatt resonnere og svare; den kan bare ikke handle, og meldingen sier hvorfor.
  • actWithApproval (og usatt) er den fail-closed-godkjenningsporten som er beskrevet ovenfor.
  • actFreely forhåndsgodkjenner alt som ikke løste seg opp til en hard deny.

Den siste fortjener å sies rett ut i stedet for å mykes opp: under actFreely blir en prompt-avgjørelse ikke eskalert til en godkjenner — den tillates, og ingen blir spurt. Bare en uttrykkelig deny-regel overlever vriden. Så actFreely er en bevisst tildeling av autonomi, ikke en bekvemmelighetsinnstilling, og fail-closed-regelen beskytter nøyaktig det tilfellet der det betyr noe (actWithApproval, standarden).

Delegering mellom agenter voktes ved kontrollpunktet delegate_task av alle fire vokterne: en dybdegrense (standard 3), syklusdeteksjon, et autonomitak (en delegat kan aldri handle med mer autonomi enn den som delegerte — privilegier kan ikke hvitvaskes ved å overlate arbeid til en friere agent) og en budsjettramme (delegering belaster det gjenstående budsjettet til oppdragsgiveren og kan ikke trylle fram mer). Hver av dem avvises høylytt, med vokterens begrunnelse returnert til agenten ordrett.

Ikke alle kjøretider lar Control Center avskjære hver handling. Eksterne agent-CLI-er kjører noen verktøy nativt, i samme prosess, der ingen port kan sitte. I stedet for å late som noe annet, har hver adapter en ærlighetsmatrise: per adapter, om Control Center filtrerer verktøyflaten, avskjærer verktøykall, observerer fullføringskontrakten, kan se kjørerens native verktøy, og om verktøy i samme prosess er dekket av en sandkasseprofil.

To oppføringer er verdt å lese før du stoler på en konfigurasjon. Den innebygde harnessen erklærer at filverktøyene dens i samme prosess ikke er sandkasset — verktøyflaten og denne policymotoren er den eneste filsystemgrensen den har. Claude Code erklærer at dens egne verktøykall ikke kan avskjæres, fordi den startes med --dangerously-skip-permissions; Control Center ser mcp__*-kallene dens og, gjennom en hook, Bash-kommandolinjene dens, mens dens egne verktøy for lesing, skriving og redigering kjører usett.

Innstillingsskjermen viser denne matrisen, for den ene utilgivelige feilen for et tillatelsesregelsystem er å påstå dekning som ikke finnes.

Tillatelsesreglene ligger under Innstillinger → Arbeidsområde → Agenttillatelser (/workspaces/<id>/settings/workspace/permissions). Skjermen har policymatrisen der regler skrives, policy-maler, en hva-om-prøve, revisjonssporet for autorisasjon og ærlighetsmatrisen for adaptere.

Prøven tar en handlingsklasse (eller en kommando) og et omfang og viser hvilken regel som bestemte og hvorfor. Fordi oppslaget er rent og deterministisk — samme handling, samme omfang, samme avgjørelse — er svaret fra prøven det svaret agenten vil få.