Gå direkt till huvudinnehåll
OpenAI

13 maj 2026

TeknikSäkerhet

Att bygga en säker och effektiv sandbox för att möjliggöra Codex på Windows

Av David Wiesen, teknisk specialist

Laddar …

När jag gick med i Codexs ingenjörsteam i september 2025 hade Codex för Windows ingen sandboximplementering, vilket innebar att Windows-användare tvingades välja mellan två undermåliga alternativ när de använde OpenAIs kodningsagenter:

  1. Att godkänna nästan varje kommando (även läsningar) som en kodningsagent ville köra, vilket är ineffektivt och irriterande. En stor fördel med att använda Codex är att du inte behöver göra allt det tråkiga arbetet själv.
  2. Att aktivera läget Full Access: låta Codex köra alla kommandon utan godkännande eller begränsningar, vilket minskar friktion på bekostnad av översyn.

Codex, vår kodningsagent, körs på utvecklarnas bärbara datorer, oavsett om det sker via CLI, IDE-tillägget eller desktopversionen. Den hanterar en konversation mellan en människa vid tangentbordet och en modell som körs i molnet för att hantera inferens.

Codex körs som standard med behörigheterna för en verklig användare, vilket innebär att den kan göra allt som användaren kan göra. Detta är kraftfullt och potentiellt farligt. Kodningsmodellen kan säga åt det underliggande systemet att köra kommandon lokalt, från att köra tester till att läsa eller redigera en fil till att skapa en Git-gren, så Codex standardläge försöker hitta rätt balans mellan effektivitet och säkerhet. Det här standardläget låter Codex läsa filer nästan var som helst och skriva filer inom din arbetsyta (dvs. katalogen där du kör Codex), utan internetåtkomst om du inte anger att du vill ha det. För att uppnå denna automatiska begränsning av filskrivning och nätverksåtkomst inom säkra ramar behöver Codex en sandboxmiljö som faktiskt upprätthåller dessa begränsningar.

En sandbox är en begränsad körningsmiljö. När en utvecklare använder Codex startar datorns operativsystem ett kommando med reducerade behörigheter, och dessa begränsningar fortplantar sig ned genom processträdet. Varje Codex-kommando sandboxas från början, och varje efterföljande process stannar inom samma gräns.

Diagram som visar operativsystemets isoleringsgränser för Codex-sandboxen.

Codex behöver isoleringsfunktioner som upprätthålls av datorns operativsystem för att implementera en effektiv sandbox. Vissa operativsystem tillhandahåller verktyg som gör detta väl (t.ex. Seatbelt på MacOs, seccomp eller bubblewrap på Linux); Windows tillhandahåller dock för närvarande inte den här typen av kapacitet direkt från start.

För att göra Codex lika säkert och smidigt att använda på Windows som det redan är överallt annars behövde vi implementera vår egen sandbox.

Där befintliga Windows-verktyg inte räckte till

Windows erbjuder vissa verktyg och mekanismer för isolering. Även om inget av dem helt uppfyllde våra krav tittade vi på ett antal möjliga lösningar – närmare bestämt AppContainer, Windows Sandbox och märkning med Mandatory Integrity Control.

AppContainer

  • Vad: AppContainer är Windows inbyggda sandbox, en kapacitetsbaserad isoleringsmodell byggd för appar som på förhand vet exakt vad de behöver få åtkomst till.
  • Varför: Attraktiv eftersom den erbjuder en verklig OS-gräns i stället för begränsningar efter bästa förmåga.
  • Varför inte: Codex är inte en enda app med snävt avgränsat användningsområde. Den driver öppna utvecklararbetsflöden: skal, Git, Python, pakethanterare, byggverktyg och vilka andra binärer agenten än bestämmer sig för att den behöver. I praktiken gjorde det AppContainer till fel form för problemet. Det var stark isolering, men för en mycket snävare klass av arbetsbelastningar än ”låt en agent arbeta som en utvecklare”.

Windows Sandbox

  • Vad: Windows Sandbox är Microsofts engångs-VM med låg vikt. Du får en ny Windows-skrivbordsmiljö med en stark isoleringsgräns, och allt du gör därinne försvinner när sessionen avslutas.
  • Varför: Intressant av uppenbara skäl – betydligt mer kompatibelt med godtycklig programvara än AppContainer, och ur säkerhetssynpunkt är det en mycket starkare sandbox.
  • Varför inte: Codex måste agera direkt på användarens faktiska checkout, verktyg och miljö, inte inuti ett separat tillfälligt skrivbord som skulle kräva konfiguration och bryggning mellan värd och gäst. Det hade också ett grundläggande produktproblem: Windows Sandbox är inte ens tillgängligt på Windows Home-SKU:er.

Integritetsmärkning med Mandatory Integrity Control (MIC)

  • Vad: Windows har ett koncept som kallas ”integritetsnivåer”, till exempel låg, medel och hög, som avgör hur mycket systemet litar på objekt och processer. Grundregeln är att en process med lägre integritet inte kan skriva till ett objekt med högre integritetsnivå, även om den normala ACL:n annars skulle tillåta det. Till exempel behandlas en process med låg integritet som mindre betrodd, så Windows blockerar den från att skriva till normala objekt med medelintegritet, om inte dessa objekt uttryckligen märks om för att tillåta det.
  • Varför: MIC såg elegant ut på pappret – kör Codex med låg integritet, märk om de skrivbara rötterna till låg integritet och låt Windows upprätthålla skrivförbud överallt annars. Det skulle ha gett oss en väg utan administratörsrättigheter med en verklig OS-mekanism bakom.
  • Varför inte: Precis som ACL:er ändrar integritetsetiketter det verkliga värdfilsystemet, och i detta fall är den semantiska förändringen särskilt bred. Att märka en arbetsyta ”låg integritet” betyder inte bara ”Codex kan skriva här”. Det betyder att processer med låg integritet i allmänhet kan skriva där. På en riktig utvecklares dator förvandlar det användarens faktiska checkout till en lågintegritetsmottagare för värden, vilket är mycket mer riskfyllt än att ge noggrant riktade ACL:er till en enda sandboxdesign. Även om utvecklarverktyg med medelintegritet fortsätter att fungera har arbetsytans underliggande tillitsmodell förändrats på ett sätt som är svårt att begränsa och ännu svårare att motivera.

Efter att ha utvärderat alla alternativen som återvändsgränder började vi utforma vår egen lösning för att ge Windows-användare en bra Codex-upplevelse.

Den första prototypen: ”sandboxen utan utökade behörigheter”

Vår första fungerande prototyp använde en kombination av Windows-koncept och verktyg för att implementera den isolering vi behövde. Från början var ett mål att få detta att fungera utan att kräva utökade behörigheter, vilket betyder att Codex inte skulle behöva be användaren om administratörsbehörighet bara för att konfigurera eller köra sandboxen. Det innebar att vi behövde hitta rimliga begränsningar för två saker: filskrivningar och nätverksåtkomst.

Begränsa filskrivningar

Om vi inte begränsade filskrivningar alls skulle vi få ett säkerhetsproblem. Om vi begränsade filskrivningar för mycket skulle sandboxen skada användarens produktivitet och behöva be om ständigt godkännande. För att lösa detta problem förlitade vi oss på två viktiga byggstenar i Windows: SID:er och skrivbegränsade token.

SID:er låter oss ge sandboxen en identitet

En SID, eller säkerhetsidentifierare, är den identitet som Windows knyter till behörigheter. Varje användare har en SID, grupper har SID:er och till och med en enskild inloggningssession får en egen SID. Till exempel kan en nuvarande inloggad session ha en SID som S-1-5-5-X-Y. SID:en som tilldelats den lokala administratörsgruppen kan vara S-1-5-32-544.

Windows låter dig också skapa syntetiska SID:er som inte motsvarar en verklig användare men som ändå kan förekomma i ACL:er (åtkomstkontrollistor), vilka definierar vem som kan läsa/skriva/köra specifika filer eller kataloger. Det gör SID:er till en användbar mekanism för vår sandbox: vi kan skapa SID:er exklusivt för Codex-sandboxen, utan att störa något annat på maskinen.

Skrivbegränsade token begränsar var Codex kan ändra filer

Processtoken är säkerhetsobjekt i Windows som definierar identitet och privilegier för en körande process. De avgör vilka åtgärder en process kan utföra. Ett skrivbegränsat token är en särskild typ av processtoken som gör att Windows utför en extra åtkomstkontroll vid skrivåtgärder.

För att en skrivning ska lyckas måste två kontroller passera:

  1. Den normala användaridentiteten (tokenets ”ägare”) måste ha tillåtelse att göra det
  2. Minst en SID i tokenets lista över begränsade SID:er måste också ha beviljats åtkomst
Diagram med titeln Skrivning i sandbox kräver både vanlig användaråtkomst och åtkomst till sandbox-write-SID.

I praktiken lät dessa kontroller oss använda ACL:er för att definiera exakt var sandboxen kunde ändra filsystemet, vilket gav den granularitet vi behövde kring skrivåtgärder.

Med SID:er och skrivbegränsade token fungerade vår sandbox utan utökade behörigheter så här:

  1. Sandboxkonfigurationen skapade en syntetisk SID med namnet sandbox-write.
  2. SID:en sandbox-write fick behörighet att skriva, köra och ta bort i
    1. Den aktuella arbetskatalogen
    2. Alla ytterligare writable_roots som konfigurerats i config.toml.
  3. Sandboxkonfigurationen nekade uttryckligen samma SID skrivåtkomst till platser som är ”skrivskyddade inom skrivbara”, till exempel:
    1. <cwd>/.git
    2. <cwd>/.codex
    3. <cwd>/.agents
  4. Codex startade kommandon under ett skrivbegränsat token vars lista över begränsade SID:er innehåller Everyone, SID:en för den aktuella inloggade sessionen och den syntetiska SID:en sandbox-write.

Detta flöde löste i praktiken begränsningen av filskrivningar och verkade lovande. Nu behövde vi en lösning för att begränsa sandboxens nätverksåtkomst.

Begränsa nätverksåtkomst

Att begränsa nätverksåtkomst är en viktig del av sandboxen, utan det skulle skadlig kod kunna exfiltrera data från maskinen ut till internet. Eftersom vi ville undvika krav på utökade behörigheter hade vi begränsade möjligheter att blockera nätverkstrafik på ett robust sätt. De verktyg vi ville använda, som Windows-brandväggen, kunde i allmänhet inte installeras utan administratörsbehörighet.

Utan Windows-brandväggen som alternativ begränsades vad vi kunde kontrollera. Vi försökte konfigurera barnmiljön så att de typer av nätverksverktyg som utvecklare faktiskt använder blockerades som standard, så att Git-kommandon, paketinstallatörer osv. skulle misslyckas i sandboxen och användaren skulle behöva godkänna alla åtgärder som kräver internetåtkomst. Idén var att blockera de uppenbara flyktvägarna: skicka trafik som använder proxyservrar till en död slutpunkt, få Gits HTTP(S)-transport att göra detsamma och få Git över SSH att misslyckas omedelbart. Utöver det lade vi till en liten katalog, denybin, först i PATH och ordnade om PATHEXT så att stubbskript för SSH och SCP hittades före de verkliga binärerna.

Till exempel är här några av de specifika miljööverskrivningar vi använde för att begränsa nätverksåtkomst:

  • HTTPS_PROXY=http://127.0.0.1:9
  • ALL_PROXY=http://127.0.0.1:9
  • GIT_HTTPS_PROXY=http://127.0.0.1:9
  • NO_PROXY=localhost,127.0.0.1,::1
  • GIT_SSH_COMMAND=cmd /c exit 1
Diagram som visar arkitekturen för sandboxen med utökade behörigheter, inklusive brandväggsregler och en dedikerad Windows-användare.

Det fångade mycket av den normala, verktygsdrivna trafiken, men det var fortfarande bara rådgivande. En process kunde ignorera miljön, kringgå PATH eller helt enkelt öppna sockets direkt – alltför riskabelt.

Tillvägagångssättet utan utökade behörighet innebar vissa kompromisser

Som med all intressant mjukvaruimplementering hade den första prototypen vissa för- och nackdelar. Även om den fick jobbet gjort med bara några få standardfunktioner i Windows, möjliggjorde mycket explicita och granulära filsystemsskrivningar och kördes utan upphöjning – vilket minskade behovet av att användare skulle acceptera alltför många upphöjningsuppmaningar eller vara administratörer på sin lokala maskin. Den hade dock några verkliga nackdelar, vilket gjorde att den inte kunde bli vår slutgiltiga design:

  • Konfigurationshastighet: Att tillämpa ACL:er på arbetsytan kan vara kostsamt beroende på arbetsytans katalogtopologi.
  • Fotavtryck: Vi tillämpade verkliga ACL:er på utvecklarens system, även om fotavtrycket inte är särskilt invasivt eftersom alla tillämpade ACL:er rör en specialskapad syntetisk SID som bara används av sandboxen.
  • Semantik som är svår att ändra: Beroendet av ACL:er för filbaserade begränsningar innebär att det är dyrt och komplext att ändra sandboxens semantik. Medan vi på macOS dynamiskt kan ändra hur vi genererar .sbpl-filen som används för att konfigurera Seatbelt, kan Windows-sandboxen behöva utföra tids- och resurskrävande åtgärder för att justera ACL:er.
  • Nätverksskyddet var svagt. Som tidigare nämnts var det endast policybaserat och kunde enkelt kringgås av program med egna nätverksstackar. Det var heller inte utformat för att hantera fientlig kod.

De tre första problemen är inneboende i en anpassad sandboximplementering som är tillräckligt flexibel för agentbaserade flöden. Historien om nätverksundertryckning var däremot annorlunda.

Nätverksundertryckning är alltför viktigt

Förutom att en skadlig agent enkelt skulle kunna kringgå den miljöbaserade nätverksundertryckningen skulle även många välmenande kodbaser/binärer kringgå den om de inte respekterade miljöns proxyvariabler eller om de implementerade egen socketbaserad nätverkskod. Vi ansåg att denna aspekt var tillräcklig för att motivera investering i ett bättre sandboxläge.

För att få bättre nätverksundertryckning ville vi använda Windows-brandväggen, som låter oss blockera utgående nätverkstrafik för användare eller program. Tyvärr kunde vi inte effektivt skapa en fungerande brandväggsregel som endast gällde kommandon som startades av Codex körmiljö av några skäl:

  • Windows tillåter inte att brandväggsregler kopplas till den identitet i ett begränsat token som inte är en säkerhetsprincipal. Det betyder att vi inte kunde tillämpa en brandväggsregel på ”vilket token som helst som innehåller vår syntetiska SID i sin lista över begränsade SID:er”.
  • Även om vi kunde skapa en brandväggsregel som matchar en specifik binär skulle det bara låta oss begränsa nätverk för själva codex.exe. Den skulle inte gälla processerna som agenten startar för användarens räkning, som Git- eller Python-processer.
  • Andra matchningsdimensioner i brandväggen hade också fel utformning. Användarspecifika regler matchade fortfarande den faktiska Windows-användaren i lösningen utan utökade behörigheter, inte bara den begränsade underprocessen. Regler baserade på programsökvägar var alltför grovkorniga: de kunde blockera codex.exe eller python.exe generellt, men inte just den här sandboxade instansen av python.exe. Regler baserade på portar eller adresser byggde dessutom på helt fel policy. Vi ville till exempel inte blockera port 443, utan snarare blockera godtycklig utgående åtkomst för just det här begränsade processträdet.

För att tillämpa en brandväggsregel specifikt på våra sandboxade kommandon behövde vi köra dem som en separat principal, inte som den ”verkliga” användaren. Detta ledde oss in på ett nytt spår där vi lättade på begränsningen att undvika utökade behörigheter.

Den omarbetade lösningen: ”sandboxen med utökade behörigheter”

Nästa version av sandboxen, som är den implementation vi använder idag, kräver administratörsbehörighet med utökade rättigheter vid installationen. Därför kallar jag den för ”sandboxen med utökade behörigheter”. Vid gränsen där Codex startar ett kommando på systemet liknar sandboxen den variant som saknar utökade behörigheter. Den kör fortfarande underprocesser med ett begränsat token – på samma sätt ett write_restricted-token med samma lista över begränsade SID:er: [Everyone, Logon, Synthetic] – men principalen för detta token är inte längre den faktiska Windows-användaren, utan i stället en av två lokala användare som Codex själv skapar:

  • CodexSandboxOffline (den som riktas av brandväggsregler)
  • CodexSandboxOnline (den som inte riktas av brandväggsregler)

Denna till synes lilla detalj har faktiskt stora konsekvenser för sandboxen, vem som kan använda den och komplexiteten i dess installation och körning.

Diagram som visar åsidosättningar av nätverksmiljön för sandboxen utan utökade behörigheter.

Den liknar prototypen utan utökade behörigheter rent visuellt, men med brandväggsregler och en dedikerad Windows-användare som faktiskt kör kommandona. (Införandet av dessa nya koncept innebär dock att det finns mer installationsarbete att göra innan sandboxen kan börja köra och skydda kommandon.)

Vi behöver nu ett fullvärdigt installationssteg

Sandboxdesignen utan utökade behörigheter hade ett enkelt installationssteg, men var relativt begränsad:

  • Skapa en syntetisk SID vid behov
  • Tillämpa ACL:er för det syntetiska SID:t ”sandbox-write”

Sandboxen med utökade behörigheter behöver däremot göra mer.

  • Skapa en syntetisk SID, om den inte redan har skapats
  • Skapa sandboxanvändarna online och offline, om de inte redan har skapats
  • Lagra de nyskapade användarnas autentiseringsuppgifter lokalt och kryptera dem med Windows Data Protection API (DPAPI) på en plats där sandboxanvändarna faktiskt inte kan läsa dem
  • Skapa brandväggsregler som blockerar all utgående nätverksåtkomst för användaren CodexSandboxOffline eller, om de redan finns, validera att de är korrekta

Installationsfasen innehåller ytterligare en komplikation. Codex sandbox förväntas ha samma läsbehörighet som den faktiska Windows-användaren. I sandboxen utan utökade behörigheter, där det begränsade tokenets primära SID var Windows-användaren, fungerade detta. Men när den primära säkerhetskontexten i stället blir en ny CodexSandbox-användare följer detta inte längre med automatiskt. Många relevanta kataloger i Windows ger läs- och körbehörighet till ”Autentiserade användare”. Ett tydligt exempel är användarens profilkatalog. Som standard kan Windows-användare inte läsa andra användares profilkataloger, vilket innebär att även enkla filläsningar skulle misslyckas i många scenarier.

För att hantera detta lade vi till ytterligare ett lager i sandboxens installationsprocess – ett för att ge sandboxanvändarna läs-ACL:er där sådana ACL:er kanske inte redan finns. Till exempel för några vanliga Windows-kataloger:

  • C:\Users\<real-user>
  • C:\Windows\
  • C:\Program Files\
  • C:\Program Files (x86)\
  • C:\ProgramData\

Eftersom den här kataloglistan bygger på en bästa möjliga-bedömning och eftersom installation av ACL:er för varje katalog kan vara ganska resurskrävande kör vi den här logiken asynkront, så att steget för att konfigurera sandboxen — som blockerar användaren — inte behöver vänta på att allt ska slutföras.

Vi kapslade in installationslogiken i en egen binär delvis för att bara korsa UAC-gränsen när det behövs. Men den djupare orsaken var arkitektonisk: sandboxinstallationen har ett fundamentalt annat jobb än codex.exe. Att hålla sandboxens installationslogik i en dedikerad binärfil gjorde att codex.exe kunde förbli ett vanligt användarprogram utan utökade behörigheter, hindrade Windows-specifik installationsmekanik från att tynga ned codex.exe på andra plattformar, frikopplade mer långvarigt installationsarbete från huvudprocessens livslängd och gav oss en plats att hantera de olika installationsvägar som sandboxen behövde.

Diagram som visar det första fullvärdiga installationssteget för sandboxen med utökade behörigheter.

Kommandoköraren är en ny binärfil som faktiskt kör användarkommandon

På grund av hur Windows hanterar användare samt inloggnings- och token-gränser kunde vi inte längre skapa ett begränsat token och starta en process under det på samma sätt som vi kunde i sandboxen utan utökade behörigheter. För att faktiskt kunna köra kommandon som en annan Windows-användare var vår första idé följande arbetsflöde:

  • codex.exe körs som den faktiska Windows-användaren. Sedan gör Codex, i följd:
    • Anropar LogonUserW(...) för sandboxanvändaren.
    • Anropar CreateRestrictedToken(...) på sandboxanvändarens token.
    • Med det begränsade sandboxanvändartokenet anropar CreateProcessAsUserW(...) för att starta det slutliga underobjektet.

I praktiken fungerade inte det önskade arbetsflödet på grund av en behörighetsbarriär vid CreateProcessAsUserW(). Det innebar att codex.exe kunde skapa ett begränsat token för sandboxanvändaren, men inte på ett tillförlitligt sätt starta en underprocess med det tokenet från den riktiga användarsidans del av gränsen. Vi behövde en process som redan kördes som sandboxanvändaren – detta skulle göra det möjligt för begränsningssteget och den slutliga processtarten att ske på sandboxanvändarsidan av gränsen i stället för på den riktiga användarsidan.

Detta krav ledde till codex-command-runner.exe, en ny binär vars enda uppgift är att skapa ett begränsat token och starta det begärda kommandot. I stället för att be codex.exe att göra hela flödet själv (verklig användare → sandboxanvändare → begränsat token → underprocess) delade vi upp flödet i två delar:

Del 1

  • codex.exe anropar CreateProcessWithLogonW(...) för att starta codex-command-runner.exe som sandboxanvändaren, utan att ännu använda ett begränsat token.

Del 2

  • Inne i körprocessen öppnar OpenProcessToken(GetCurrentProcess(), ...) körprocessens eget token, som redan tillhör sandboxanvändaren.
  • Körprocessen anropar GetTokenInformation(...) för att extrahera sandboxens logon-SID, därefter CreateRestrictedToken(...) för att bygga det slutliga begränsade tokenet.
  • Fortfarande inne i körprocessen anropar den CreateProcessAsUserW(...) med det begränsade tokenet för att starta den verkliga underprocessen.
Diagram som visar hur kommandoköraren används för att starta begränsade kommandon.

Helhetsbilden

Albert Einstein sa: ”Allting bör göras så enkelt som möjligt, men inte enklare.” I den andan löste vår design varje problem på ett tillräckligt bra sätt. Den slutliga arkitekturen har de fyra lager vi tidigare har gått igenom:

  • codex.exe självt
  • codex-windows-sandbox-setup.exe för att hantera allt installationsarbete som rör utökade rättigheter
  • codex-command-runner.exe för att köra kommandon med begränsade token
  • Underprocessen

När jag först tog mig an det här projektet hade jag ingen tydlig bild av var det skulle landa. Min utgångspunkt var att börja instrumentera sandboxfunktionen i gränsytan mellan Codex och operativsystemet. Det här tillvägagångssättet ligger nära hur Codex sandbox är implementerad på macOS och Linux.

När jag lärde mig mer om de specifika verktyg som Windows tillhandahåller, och genom dussintals beslut som balanserade säkerhet och användarvänlighet, växte systemet till sin nuvarande form – flera binärer, anpassade användare, brandväggsregler, ett upphöjt installationssteg, asynkrona processer med mera.

Det är inte ett särskilt enkelt system, men varje komplexitetsdel lades till av nödvändighet, för att bygga en sandbox som både är säker och så långt som möjligt inte står i vägen för användaren.

Diagram som visar den slutliga arkitekturen för Windows-sandboxen.

Att balansera säkerhet med faktisk användbarhet

När vi arbetade för att leverera en bra användarupplevelse för Codex-användare på Windows var vårt mål att skapa något säkert som inte kompromissade med användbarheten – hela poängen med att använda Codex är att låta agenter kunna utföra arbete utan din ständiga uppmärksamhet.

En av de största lärdomarna från projektet var att Windows inte gav oss en enda primitiv som rent mappar till ”säker autonom kodningsagent”. Vi kombinerade flera verktyg och koncept för att bygga något sammanhängande. Vissa tidiga idéer var återvändsgränder. Den slutliga designen var en hybrid av tidigare prototyper som var och en löste en del av problemet.

Den andra lärdomen var att säkerhet för en kodningsagent är något annat än mer klassisk applikationssäkerhet. Codex måste fungera för verkliga utvecklararbetsflöden. Ingenjörsarbetet handlade om att balansera kompatibilitet med agentbaserade arbetsbelastningar mot faktisk upprätthållning av begränsningar. Den spänningen formade kompromisserna i den slutliga designen.

Nyfiken på att se hur Codex-sandboxen fungerar i praktiken? Prova den.