Gemini CLI vymazal z balíčků klíč, o kterém Chrome DevTools píše, že je veřejný
Gemini CLI 0.60.0 odstranil ze svých balíčků klíč k rozhraní Google CrUX, který se do nich dostával z knihovny chrome-devtools-mcp. Přijatý návrh změny ho popisuje jako natvrdo zapsaný přihlašovací údaj podle CWE-798; zdrojový kód Chrome DevTools u téhož klíče uvádí, že má být ve frontendu vidět. V knihovně od Googlu klíč zůstal.
Verze 0.60.0 nástroje Gemini CLI vyšla 15. září. Mezi jejími změnami je jedna, která nemění chování programu, ale obsah balíčku: ze souborů stažených z registru npm zmizel klíč k rozhraní Google CrUX. Do balíčku se dostával z knihovny chrome-devtools-mcp, přes kterou Gemini CLI ovládá prohlížeč.

Návrh té změny ji popisuje jako odstranění natvrdo zapsaného přihlašovacího údaje a odkazuje na CWE-798, tedy na kategorii „použití natvrdo zapsaných přihlašovacích údajů“. Ten klíč ale nikdy tajný nebyl. Oba projekty, které ho nesou, to mají napsané ve zdrojovém kódu.
Klíč, který má být vidět
CrUX je veřejná databáze Googlu s údaji o rychlosti webů tak, jak ji zažili skuteční návštěvníci Chromu. Vývojářské nástroje Chromu si z ní tahají čísla k právě měřené stránce a klíč, kterým se u rozhraní hlásí, je součástí jejich kódu. V souboru CrUXManager.ts stojí přímo nad ním poznámka „This key is expected to be visible in the frontend“, tedy že ten klíč má být ve frontendu vidět, a pod ní číslo vnitřního záznamu Googlu.
Knihovna chrome-devtools-mcp, která z těch nástrojů dělá server MCP, nese klíč taky. Komentář u něj je ještě přímočařejší: říká, že „this API key is public“, a končí smajlíkem.
Co oprava doopravdy udělala
Na knihovnu ani na kód nástroje změna nesahá. Přidává krok do skriptu bundle-browser-mcp.mjs, který knihovnu balí. Po sestavení projede dva výstupní soubory, najde v nich řetězec ve tvaru googlovského klíče k rozhraní a nahradí ho čtením proměnné prostředí CRUX_API_KEY. Když po záměně nějaký klíč v souboru zbude, skript balení shodí chybou.
Vzor, kterým klíč hledá, je obecný a sedí na kterýkoli googlovský klíč v uvozovkách. Náhrada je naopak jediná: každý nález se přepíše na tutéž proměnnou, i kdyby patřil úplně jinému rozhraní.
Na vydaných balíčcích je to vidět. Ve verzích 0.55.1 až 0.59.0 klíč v souborech dist/bundled/chrome-devtools-mcp.mjs a dist/bundled/third_party/index.js je, ve verzi 0.60.0 na jeho místě stojí čtení proměnné. Je to vlastní měření: balíčky se stáhly z registru npm a prohledaly na vzor googlovského klíče.
Uživatelům se oprava dostala do ruky až napodruhé. Verze 0.59.0 vyšla 8. září, tedy po přijetí té změny, jenže balicí skript v ní ten krok ještě nemá a klíč v jejích souborech pořád je; její seznam změn mířil jinam, na servery MCP z nedůvěryhodné složky.
Test, který chce, aby klíč zůstal
Součástí změny je nový test cruxKeyLeak.test.ts. Klíč v něm není napsaný přímo, ale zakódovaný v base64, takže ho hledání v repozitáři nenajde. Test má čtyři tvrzení a to první žádá, aby klíč v nainstalované knihovně pořád byl: sáhne do node_modules a skončí chybou, když ho tam nenajde. Kdyby ho Google z knihovny odstranil, rozbije se test, který má jeho únik hlídat.
Zbylá tři tvrzení hlídají, že v sestavených souborech klíč není. Každé z nich je ale uvnitř podmínky „když ten soubor existuje“, takže na stroji, kde se balíček nesestavoval, projdou, aniž co změří.
Proměnná, kterou dokumentace nezná
Po záměně se klíč čte z proměnné prostředí CRUX_API_KEY. V celém zdrojovém stromu verze 0.60.0 se to jméno vyskytuje jedinkrát, a to právě v balicím skriptu; dokumentace, nápověda ani ukázková nastavení ho neznají. Vlastní měření nad zdrojovým archivem vydání, 3 000 souborů.
Bez nastavené proměnné se do adresy rozhraní dosadí prázdný řetězec. Dotaz na chromeuxreport.googleapis.com bez klíče odpoví kódem 403 a hláškou, že rozhraní nepřijímá volající bez prokázané totožnosti; vyzkoušeno 17. září. Že Gemini CLI tu cestu používá, je vidět v jeho vlastním kódu: souhlas, který si vyžádá před prvním spuštěním prohlížeče, upozorňuje, že výkonnostní nástroje můžou posílat adresy do rozhraní CrUX, a když má uživatel vypnuté statistiky užívání, spustí nástroj knihovnu s přepínačem --no-performance-crux.
Jestli po záměně ta funkce opravdu přestane fungovat, se zvenčí změřit nedá. Jisté je, že se adresa sestaví bez klíče a že takový dotaz rozhraní odmítá.
Co po opravě zbylo
Vyčistit balíček má smysl i bez ohledu na to, jestli je klíč tajný. Bezpečnostní skenery hledají v obrazech kontejnerů a v balíčcích řetězce ve tvaru klíčů k rozhraním a každý takový nález musí někdo projít a odmítnout. O jeden se jich tou změnou ubralo Gemini CLI i každému, kdo si jeho balíček rozbaluje do vlastního obrazu.
Zařazení pod CWE-798 v přijatém návrhu zůstává, ačkoli je ani jeden z dotčených projektů nesdílí. A klíč se z knihovny nikam neposunul: poslední vydání chrome-devtools-mcp z 8. září nese googlovské klíče dva. Ten druhý je v souboru s výkonnostními nástroji a má ho i verze 0.19.0 z letošního března, na které Gemini CLI stojí. Do sestaveného balíčku se nedostane. Kdyby se dostal, vzor by ho minul, protože je zapsaný uvnitř adresy a vzor si žádá uvozovku těsně před klíčem; balení by pak skončilo chybou, kterou skript vyhodí pokaždé, když po záměně nějaký klíč zbude.
Zdroje: návrh změny 29158 a poznámky k vydání 0.60.0 v repozitáři Gemini CLI, soubor CrUXManager.ts ve vývojářských nástrojích Chromu, repozitář chrome-devtools-mcp a balíčky obou projektů v registru npm.