OpenAI včera zveřejnil report o incidentu z 27. května: interní model měl v systémovém promptu výslovný zákaz sahat na GitHub Actions. Zákaz dodržel. Místo workflow přepsal skript, který to workflow spouští — a přes něj poslal do veřejného repozitáře výzkumníkův GitHub token, rozdělený na tři kusy „aby prošel scannerem". Uživatel mu přitom dvakrát řekl, ať to nedělá, a model dvakrát slíbil, že přestane. Tohle není článek o tom, že AI zlobí. Je o hranici, kterou má ve firmě skoro každý postavenou stejně špatně.
Co se stalo
- Zdroj a datum. Případ popisuje report Exposing a GitHub token in a public repository, zveřejněný 25. září 2026 v rámci rámce OpenAI pro hlášení odchylek. Incident i jeho odhalení datuje report na 27. května 2026. Všechna čísla a citace níže jsou z toho reportu, ne z převzatých článků.
- Zadání bylo nudné. Model pracoval s výzkumníkem na matematickém důkazu v systému Lean. Nešlo o bezpečnostní test. Model se v důkazu zasekl a začal hledat, jak se dostat k řešení, které odevzdal jiný tým.
- Zákaz byl konkrétní a napsaný předem. V systémové instrukci stálo doslova: „Never create or modify a github action unless its done so as part of a existing generation script or the user explicitly asked you to." A hned vedle: „if you are missing a credential, do not look for alternative paths to get new credentials. Instead, let the user know that you are blocked." Tedy přesně ten scénář, který nastal, byl dopředu zakázán.
- Člověk zasáhl dvakrát. Nepomohlo to. Když model navrhl použít dočasnou GitHub Action na stažení cizích výsledků, výzkumník odpověděl: „Please construct the proof locally." Model souhlasil a zapsal si do vlastní poznámky: „Do NOT pursue artifact/action workaround now." Druhý den požádal znovu, dostal „You should solve the problem yourself", znovu souhlasil, znovu si to poznamenal — a pak se k tomu vrátil potřetí. V zaznamenané úvaze je přitom vidět, že si zákaz pamatoval: „But user said solve ourselves; exploit infrastructure questionable. Still."
- Jak obešel zákaz, aniž ho porušil. Model si vypsal repozitáře organizace, do kterých má zapisovat (
gh repo list openai --json nameWithOwner,viewerPermission,isPrivate), a našel veřejnýopenai/codexs právem WRITE. Pokus nahrát tam vlastní workflow selhal — GitHub push odmítl sGH013: Repository rule violations found, „File path is restricted". Model na to reagoval úvahou, že může upravit „non-workflow source", který stávající CI spustí samo, a přepsal soubor.github/scripts/verify_cargo_workspace_manifests.py. Ten se ve workflow volá při každém pull requestu. Push prošel, model otevřel veřejný PR a CI jeho program spustilo. - Token rozdělený na tři části. První běh vrátil chybu 401 — ve spouštěném kroku žádný token není. Model proto do skriptu vložil výzkumníkův vlastní token získaný přes
gh auth token, a to v podobětok = '[...]' + '[...]' + '[...]'s komentářem# token split to avoid scanners. Záměr obejít detekci tajemství je zaznamenaný i v úvaze modelu. Push prošel a token skončil ve veřejném repozitáři. - Data ven tekla přes výstup testu. Jako zpětný kanál model použil annotations, tedy chybové zprávy připojené k výsledku automatické kontroly, čitelné přes API. Nakonec si lokálně vygeneroval podepsanou stahovací adresu (platnou zhruba deset minut), vložil ji do skriptu a nechal runner stáhnout log cizího běhu. Vrátilo se deset anotací s částmi logu z 20. května, včetně metadat
"submission_public": falsea identifikace zdrojového repozitáře a revize. Zdrojový kód důkazu model podle reportu nezískal. - Co to stálo. Výzkumník nahlásil věc bezpečnostnímu týmu. OpenAI deaktivovalo klíče dotčených uživatelů a následně preventivně klíče všech zaměstnanců. Model byl odstaven zhruba na dva týdny a vrátil se s vynuceným schvalováním všech akcí, monitorem úvah, který ho umí vypnout během minut, a kontrolou každých 30 minut místo jednou za kontextové okno. Klíčová věta reportu: „Our misalignment monitoring system flagged the trajectory, but in this case the researcher happened to be faster." Automatika to viděla. Zastavil to člověk, který se náhodou díval.
Co jsem si ověřil sám
Report je anonymizovaný jen částečně — uvádí konkrétní repozitář, konkrétní soubor a konkrétní číslo pull requestu. To se dá ověřit zvenčí, tak jsem to udělal.
- PR je pryč, větev ne. Adresa
github.com/openai/codex/pull/24788dnes přesměrovává na issue se stejným číslem a to vrací HTTP 404. Čtyři commity, které report cituje, přes API nejsou dohledatelné. Větevpia-relay-codeale v repozitáři pořád existuje a ukazuje na commit155905c— tedy přesně ten, který se v reportu objevuje v řádku „HEAD is now at 155905c make vercel webhook url an env secret (#24778)". Ten commit je veřejně datovaný 27. 5. 2026 17:00 UTC, pár hodin před incidentem. Větev tedy nebyla smazána, jen převinuta na čistý stav. To zároveň nezávisle potvrzuje, že se popisovaná věc opravdu odehrála v tomhle repozitáři a v ten den. - Konstrukce, kterou model zneužil, je běžná a je tam dodnes. Soubor
.github/workflows/blocking-ci.ymlse spouští napull_request: {}a volárepo-checks.yml, který má krokrun: python3 .github/scripts/verify_cargo_workspace_manifests.py. Ten skript se v repozitáři nachází a má dnes 395 řádků. Není to chyba OpenAI — takhle vypadá CI ve většině repozitářů světa. Pointa je jinde: ochrana byla nastavená na cestu k souboru (.github/workflows/), zatímco vykonat kód umí i soubor mimo ni. - Co ho ve skutečnosti zastavilo, nebyla ta zábrana. První pokus selhal na HTTP 401, protože v tom kroku prostě žádný token není. Až proto model sáhl po lidském tokenu. V dnešní verzi workflow je vidět i
persist-credentials: falseu checkoutu, tedy že přihlašovací údaje se po stažení kódu nenechávají ležet — to je přesně ta vrstva, která tady rozhodovala. Zajímavost pro úplnost: souborCODEOWNERShlídá povinné schválení pro release workflow, podepisovací skripty i sám sebe, ale pro tenhle kontrolní skript pravidlo nemá.
Co naopak nevíme: report neuvádí, jak dlouho byl token veřejně dostupný, ani jestli ho stihl kdokoli zvenčí stáhnout. Říká jen, že klíče byly deaktivovány. Kdo dnes tvrdí, že „nedošlo k žádné škodě", to z tohoto zdroje nemá.
Proč se to týká i vás
Česká firma bez vlastního modelu si z toho může odnést tři věci a žádná z nich není „AI je nebezpečná".
První: zákaz napsaný v promptu není zábrana, je to přání. Model dostal explicitní zákaz, dvakrát ho potvrdil, dokonce si ho zapsal do vlastních poznámek — a pak ho obešel cestou, která jeho doslovné znění neporušovala. Pokud máte pravidla pro agenta formulovaná jako věty v systémovém promptu („nesahej na produkci", „needituj CI"), máte doporučení. Zábrana je až to, co model technicky nepustí dál: chybějící oprávnění, chybějící token, oddělená síť.
Druhé: ochrana vázaná na cestu k souboru chrání cestu, ne schopnost. Tohle je z celého případu nejpřenositelnější poučení a netýká se jen AI. Když si chráníte .github/workflows/, ale ne skripty, které se z nich volají, chráníte název adresáře. Totéž platí pro chráněné větve bez chráněných skriptů, pro schvalování „jen u migrací" nebo pro review povinné jen na určitých souborech. Zeptejte se u každé takové ochrany: co všechno se v tomhle systému nakonec spustí? Odpověď je skoro vždy širší než seznam chráněných cest.
Třetí: kanál pro únik dat nemusí vypadat jako kanál pro data. Model neposílal data e-mailem ani na cizí server. Posílal je jako chybové hlášky v logu testu, které si pak četl přes API. Když ve firmě sledujete, kam agent posílá soubory, ale nikdo se nedívá na to, co se objevuje ve výstupech CI, máte slepé místo přesně v místě, které nikdo nepovažuje za citlivé.
Co s tím
- 1. Projděte, co všechno váš CI spustí při pull requestu od agenta. Nejde o seznam workflow souborů, ale o seznam všeho spustitelného, co se z nich volá — skripty, hooky, build soubory, testy. Jestli je ten seznam delší, než čekáte, je to přesně ten rozdíl mezi chráněnou cestou a chráněnou schopností. Zabere to jedno odpoledne a nepotřebujete k tomu nikoho zvenčí.
- 2. Zkontrolujte, jestli agentovi po checkoutu nezůstávají v prostředí přihlašovací údaje. V GitHub Actions je to
persist-credentials: false, jinde ekvivalent. V tomhle případu právě nepřítomnost tokenu v tom kroku rozhodla o tom, že první pokus skončil chybou 401. - 3. Vezměte oprávnění, ne slib. U každého agenta si vypište, do čeho může zapisovat — ne co má zakázáno. Model si ten seznam vypsal jedním příkazem a našel si veřejný repozitář s právem zápisu, o kterém pravděpodobně nikdo aktivně nevěděl. Vy si ho můžete vypsat úplně stejně.
- 4. Berte výstupy CI jako data, která mohou opustit firmu. Logy, anotace a chybové hlášky bývají čitelné šířeji než samotný repozitář a nikdo je nepovažuje za citlivé. Stačí vědět, kdo je může číst.
A teď proti vlastnímu byznysu: pokud ve firmě nepouštíte žádného agenta do repozitáře ani do CI a AI u vás znamená, že si lidé nechávají přepisovat e-maily v ChatGPT, tenhle případ pro vás neznamená vůbec nic. Žádný úkol, žádný audit, žádná schůzka. Nejde o zranitelnost v produktu, který používáte — jde o incident v interním výzkumném prostředí výrobce. Kdo vám tenhle týden zavolá, že „OpenAI uniklo tokeny, potřebujete ochranu", vám prodává titulek. Nejdřív by se měl zeptat, jestli vůbec máte agenta s právem zápisu.
Kde to řeším s klienty
Kde to naopak dává smysl probrat, je firma, která agentům skutečně dala přístup do repozitáře, CI nebo interních systémů. Tam je potřeba mít na papíře, co agent smí spustit, čím je to vynucené (oprávněním, ne větou v promptu) a kdo to uvidí, když se to stane. To je obsah AI Agent Governance Checkupu. Když si nejste jistí, kam až vaši agenti dosáhnou, začněte AI Risk Scanem zdarma. Ke stejnému vzorci „zábrana platila na to, co bylo napsané, ne na to, co šlo udělat" jsem se dostal už u guardrailu, který nečte pravidlo, u agenta, který si vypnul sandbox jedním příkazem i u allowlistu domén podle přípony. Předchozí reporty ze stejné řady jsem rozebíral v textu o instrukcích, které si model psal do vlastních shrnutí.