Jak bezpečně pracovat s cizím Git repozitářem

Cizí Git repozitář je běžná součást práce. Open source projekt, kód od dodavatele, zadání pracovního pohovoru, nový projekt v týmu nebo repo, které vám někdo pošle s prosbou o kontrolu.

Naklonovat ho je normální. Z bezpečnostního hlediska je zajímavé hlavně to, co nad tím adresářem začne běžet potom.

Editor může načíst konfiguraci projektu. Package manager může při instalaci spustit skripty. Build a testy spouštějí další kód. Submoduly mohou stáhnout další repozitáře. Coding agent může několik těchto kroků provést automaticky. A pokud jste místo normálního clone dostali celý adresář včetně .git, může chování samotného Gitu ovlivnit i lokální konfigurace repozitáře.

Neznamená to, že každý cizí projekt potřebuje vlastní forenzní laboratoř. Dává ale smysl vědět, ve kterém okamžiku už projekt pouze nečtete, ale dovolujete mu něco spustit.

Otevřít projekt nemusí znamenat jen zobrazit zdrojáky

Moderní editor nebo IDE není pasivní textový prohlížeč. Nad otevřeným projektem může načítat jeho vlastní nastavení, spouštět tasky, připravovat debugger, inicializovat build systém nebo aktivovat další projektovou automatizaci.

Proto například VS Code používá pro neznámé projekty Workspace Trust a Restricted Mode. Dokud projektu nedůvěřujete, omezuje mimo jiné tasks, debugging a některá workspace nastavení. JetBrains IDE mají podobný Safe Mode, ve kterém lze zdrojáky prohlížet bez spuštění například Maven nebo Gradle importu a dalších projektových skriptů.

Pokud editor při otevření neznámého projektu nabízí volbu typu „Trust this project?“, není to jen právní dialog k odkliknutí. Rozhoduje se tím mimo jiné o tom, které funkce projektu se smějí automaticky aktivovat.

Pro první prohlídku cizího repozitáře je proto vhodné nechat podobný restricted nebo safe režim zapnutý, pokud ho používaný nástroj nabízí.

Instalace závislostí už může spouštět kód

Další hranice je příprava projektu ke spuštění.

U JavaScriptového projektu najdete v README běžně například:

npm install
npm run dev

npm install přitom není pouze stažení souborů do node_modules. npm během instalace standardně podporuje lifecycle skripty jako preinstall, install, postinstall nebo prepare. Ty jsou normální součástí ekosystému a řada legitimních balíčků je používá. Zároveň jde o programový kód spuštěný během instalace.

U cizího projektu se proto vyplatí před instalací podívat minimálně na package.json a na to, jaké skripty projekt definuje.

Při první kontrole lze npm spustit také s vypnutými skripty:

npm install --ignore-scripts

Tím npm při instalaci nespustí skripty z package.json. Není to sandbox ani důkaz, že je projekt bezpečný. Explicitní npm run dev, npm test nebo jiný příkaz určený ke spuštění skriptu svůj cílový skript stále provede.

Má to ale praktické použití: lze oddělit samotnou instalaci závislostí od dalšího kódu, který se má během instalace automaticky spouštět.

Stejný princip platí i mimo npm. Maven, Gradle, Python packaging, Make, Cargo a další build nebo package systémy mají vlastní mechanismy, kterými mohou během setupu a buildu spouštět další programy. Konkrétní příkazy se liší, bezpečnostní otázka je stejná: co všechno se skutečně provede, když udělám krok popsaný jako instalace, build nebo test?

Škodlivý příkaz nemusí vypadat škodlivě

Tohle jsem si vyzkoušel na skutečném škodlivém repozitáři z falešné pracovní nabídky.

README obsahovalo normální instrukci:

npm run dev

Projekt po jejím spuštění skutečně nastartoval. Současně se ale aktivoval škodlivý kód, který si zjistil adresu svého serveru, stáhl další část programu a začal se zapisovat do vývojářských nástrojů.

Podstatné nebylo, že by někde v návodu stálo run-malware. Útočník schoval škodlivé chování za krok, který člověk při kontrole frontendu udělá úplně normálně.

Celý ten případ jsem rozebral v článku Spustil jsem malware. Adresu svého serveru si našel v blockchainu.

Proto nestačí hledat jen příkazy, které na první pohled vypadají nebezpečně. Důležité je také to, co běžný příkaz spustí dál a jaké další soubory nebo data si za běhu načte.

Coding agent může stejný řetězec projít sám

Coding agent tenhle problém nevytváří, ale umí ho výrazně zrychlit.

Když agent dostane úkol typu „projdi tenhle projekt a vysvětli mi ho“, může zůstat u čtení souborů. U zadání „rozběhni projekt“, „oprav testy“, „najdi chybu“ nebo „ověř, že aplikace funguje“ už může být instalace závislostí, build nebo spuštění testů normální součástí řešení.

Agent tedy nemusí udělat nic proti zadání. Může přesně splnit požadovaný úkol a přitom spustit škodlivý instalační nebo build skript.

Proto je důležitější omezit prostředí, ve kterém agent pracuje, než spoléhat na to, že pokaždé správně pozná nebezpečný příkaz.

Například Claude Code odděluje permissions a sandbox. Permissions určují, které nástroje smí agent použít. Sandbox pak na úrovni operačního systému omezuje filesystem a síť pro Bash i pro procesy, které Bash spustí. Omezení se tedy vztahuje také na npm, build skripty a další potomky spuštěných procesů.

Sandbox lze v Claude Code zapnout pomocí:

/sandbox

Pro skutečně nedůvěryhodný projekt dává smysl kombinovat sandbox s omezením přístupu k citlivým souborům a síti. Samotné potvrzování jednotlivých příkazů není stejně silná ochrana. U dlouhé série běžně vypadajících operací navíc rychle vzniká approval fatigue a člověk začne potvrzení odklikávat automaticky.

Jeden repozitář může přivést další

Git submoduly umožňují, aby hlavní projekt odkazoval na další Git repozitáře. Jejich konfigurace je uložená v souboru .gitmodules, který je normální součástí repozitáře.

Proto je rozdíl mezi:

git clone https://example.com/project.git

a:

git clone --recurse-submodules https://example.com/project.git

Ve druhém případě Git rovnou začne řešit i další repozitáře uvedené v projektu.

U neznámého projektu není důvod stahovat submoduly automaticky dřív, než se podíváte, kam odkazují. Stačí nejdřív zkontrolovat .gitmodules a teprve potom je podle potřeby inicializovat.

Git má pro automaticky vyvolané síťové operace vlastní protocol policy. Některé protokoly jsou standardně povolené, nebezpečnější ext je zakázaný a další mohou mít politiku user, která rozlišuje mezi přímou akcí uživatele a automatickou operací vyvolanou například submodulem.

Tyto defaulty není potřeba kvůli běžné práci měnit. Naopak není dobrý nápad je globálně povolovat volněji jen proto, že nějaký konkrétní projekt jinak nefunguje, aniž by bylo jasné proč.

Cizí .git je jiný případ

Doteď jsme počítali s normálním vzdáleným repozitářem, který si sami naklonujete.

Jiná situace nastane, když vám někdo pošle celý pracovní adresář například jako ZIP, přes sdílený disk nebo synchronizovanou složku:

project/
├── src/
├── package.json
├── README.md
└── .git/

V takovém případě jste nedostali jen zdrojové soubory a Git historii. Dostali jste také cizí lokální Git metadata.

Tady je důležitý rozdíl proti běžnému git clone. Při vzdáleném clone se lokální .git/config původního repozitáře ani jeho hooks nekopírují. Git si na vašem stroji vytvoří nový .git adresář a vlastní lokální konfiguraci.

Pokud ale někdo předá celý adresář včetně .git, dostáváte i konfiguraci a hooks, které připravil on.

Oficiální dokumentace Gitu na to upozorňuje přímo: některé konfigurační volby a hooks mohou spouštět libovolné příkazy, a proto není bezpečné normálně pracovat s .git, který pochází z nedůvěryhodného zdroje.

Aktuální příklad: GitSpawn a core.fsmonitor

Konkrétní ukázkou je výzkum GitSpawn od Manifold Security.

Git podporuje nastavení core.fsmonitor, které mu pomáhá rychleji zjišťovat změny souborů. Hodnotou ale může být také externí program.

V lokálním .git/config tedy může být nastavení ve smyslu:

[core]
    fsmonitor = <program>

Někteří coding agenti po otevření Git repozitáře automaticky zjišťovali jeho stav pomocí Git příkazů. Při operaci, která potřebovala obnovit index, Git použil nastavený fsmonitor a spustil cizí program.

Takže i normálně vypadající:

git status

mohlo skončit spuštěním programu definovaného v podstrčeném .git/config.

Pro tuhle konkrétní cestu lze při automatickém zjišťování stavu použít:

git -c core.fsmonitor=false status

Volba -c přepíše konfiguraci pro právě spouštěný Git příkaz. Hodnota core.fsmonitor z repozitáře se tedy pro tento příkaz nepoužije.

Globální:

git config --global core.fsmonitor false

není proti škodlivému repo-local nastavení spolehlivá ochrana. Lokální .git/config má vyšší prioritu než globální konfigurace a může ji přepsat.

git -c core.fsmonitor=false status zároveň není obecné zabezpečení Gitu. Řeší konkrétní cestu přes core.fsmonitor. Git konfigurace i hooks mají další možnosti, jak ovlivnit chování programu.

safe.directory není seznam důvěryhodných projektů

Git má ochranu proti repozitářům vlastněným jiným uživatelem.

Ve výchozím stavu odmítne pracovat s repozitářem, který patří někomu jinému, a nebude ani parsovat jeho lokální config nebo spouštět hooks. Konkrétní výjimky lze přidat pomocí safe.directory.

To je užitečné například na víceuživatelském systému.

Není to ale obecná ochrana proti škodlivému repozitáři. Když si sami rozbalíte ZIP připravený někým jiným, výsledné soubory typicky vlastní váš účet. Git tedy nemá podle ownershipu důvod takový adresář odmítnout.

A pokud Git zahlásí problém s „dubious ownership“, není vhodné ho automaticky řešit:

git config --global --add safe.directory '*'

Hodnota * kontrolu ownershipu globálně vypne. Lepší je zjistit, proč má konkrétní repo jiného vlastníka, a případnou výjimku nastavit jen tam, kde ji skutečně potřebujete.

Když cizí .git opravdu potřebujete

Někdy není k dispozici původní vzdálený repozitář a potřebujete zachovat historii, branche nebo další Git metadata z předaného adresáře.

Git v takové situaci doporučuje nevstupovat běžně do původního repozitáře, ale nejdřív z něj vytvořit čistou kopii:

git clone --no-local /cesta/k/puvodnimu-repu /cesta/k/nove-kopii

--no-local zabrání použití optimalizací lokálního clone a Git vytvoří nový repozitář prostřednictvím svého běžného transportního mechanismu. Výsledná kopie tak nepřebírá původní lokální config a hooks.

Ani to není absolutní sandbox. Serverovou část clone obsluhuje git-upload-pack a samotná Git dokumentace upozorňuje, že i ten má vlastní attack surface. U skutečně nedůvěryhodného .git proto doporučuje spustit tuto část pod neprivilegovaným uživatelem nebo použít další izolaci.

Pokud historii vůbec nepotřebujete, je jednodušší původní .git nepoužívat.

Omezit lze i automatické hledání bare repozitářů

Git umí pracovat také s bare repositories, tedy repozitáři bez běžného working tree.

Pokud je ve svém workflow nepoužíváte, Git nabízí jedno užitečné hardening nastavení:

git config --global safe.bareRepository explicit

Git pak nebude automaticky pracovat s bare repozitářem, který pouze objeví uvnitř adresářové struktury. Musí mu být určený explicitně.

Git dokumentace tuto volbu doporučuje zvážit právě jako ochranu proti útokům, kdy naklonovaný projekt obsahuje další bare repository a následný Git příkaz ho automaticky najde.

Když projekt opravdu musíte spustit

Statická kontrola má svoje limity. Někdy potřebujete aplikaci skutečně spustit, reprodukovat chybu, pustit testy nebo sledovat její chování.

V tu chvíli už víte, že budete spouštět cizí kód. Nejdůležitější proto není další jednotlivá volba Gitu, ale prostředí, ve kterém ten kód poběží.

Běžný pracovní účet vývojáře může mít přístup k SSH klíčům, privátním repozitářům, Git a cloudovým tokenům, produkčním .env, uloženým přihlášením, dalším zdrojovým kódům nebo běžícím credential agentům.

Cizí projekt většinu z toho nepotřebuje.

U projektu, kterému nedůvěřujete, ale potřebujete ho spustit, dává smysl použít jednorázové nebo jinak omezené prostředí bez skutečných přístupových údajů a bez zbytečného přístupu k datům hostitele.

Podle rizika může jít o sandbox, separátní uživatelský účet, development environment vytvořený právě pro tento účel nebo jednorázový virtuální systém.

Container může být součástí takového řešení, ale samotné „běží to v Dockeru“ ještě neznamená dobrou izolaci. Docker bind mounty mají ve výchozím stavu právo zapisovat do namountovaných souborů hostitele. Přístup k Docker daemonu je ještě silnější; Docker dokumentace výslovně upozorňuje, že možnost ovládat daemon poskytuje root-level oprávnění na hostitelském systému.

U nedůvěryhodného kódu bych proto do containeru nepředával Docker socket, celý domovský adresář, SSH agent ani adresáře s credentials. Pokud projekt potřebuje hostitelský adresář pouze číst, je vhodnější read-only mount než zápis.

Stejně důležitá je síť. Pokud projekt ke své funkci nepotřebuje libovolný odchozí přístup, není důvod mu ho automaticky dávat.

Snapshot virtuálního systému je užitečný pro návrat disku do předchozího stavu. Není ale bezpečnostní hranice proti úniku dat. Token, který už cizí program odeslal ven, rollback nevrátí.

Praktický bezpečnostní baseline

Žádné z následujících opatření samo o sobě nedělá cizí repozitář důvěryhodným. Jednotlivé kroky omezují různé cesty, kterými může projekt nebo nástroje kolem něj spouštět kód a získávat přístup k okolnímu systému.

Situace Co udělat / nastavit Proč Co to neřeší
První otevření cizího projektu Použít Restricted / Safe Mode, pokud ho editor nebo IDE podporuje. Omezí automatické tasks, buildy a projektovou konfiguraci před kontrolou. Nechrání před kódem, který později sami spustíte.
První npm instalace npm install --ignore-scripts Zabrání automatickému spuštění lifecycle skriptů během instalace. Není to sandbox. Explicitní npm run svůj cílový skript spustí.
Git submoduly Nezačínat automaticky s --recurse-submodules; nejdřív zkontrolovat .gitmodules. Hlavní repo může odkazovat na další zdroje kódu. Neříká nic o bezpečnosti samotného hlavního repozitáře.
Git protocol policy Bez konkrétního důvodu neuvolňovat globálně protocol.*.allow. Git má bezpečnostní defaulty pro automaticky vyvolané transporty a submoduly. Povolený HTTPS nebo SSH remote může stále obsahovat škodlivý kód.
Repo s jiným vlastníkem Nepoužívat globálně safe.directory=*. Povolit jen konkrétní adresář, pokud je to skutečně potřeba. Zachová ownership ochranu Gitu. Nechrání před škodlivým repem, které už vlastní váš účet.
Bare repositories git config --global safe.bareRepository explicit, pokud bare repositories běžně nepotřebujete. Omezí automatické objevení bare repozitáře vloženého do cizího projektu. Neřeší normální working-tree repozitáře ani jiné execution paths.
Cizí celý .git git clone --no-local /zdroj /nova-kopie Vytvoří nový .git místo běžné práce přímo nad cizím configem a hooks. git-upload-pack má vlastní attack surface; vysoce nedůvěryhodný zdroj patří do izolace.
Automatický git status nad nedůvěryhodným .git git -c core.fsmonitor=false status Pro tento příkaz nepoužije podstrčený core.fsmonitor z repozitáře. Řeší pouze tuto konkrétní GitSpawn cestu.
Coding agent Použít sandbox a omezit filesystem i síť. U Claude Code například /sandbox. Omezení platí také pro procesy spuštěné agentem, například npm nebo build skripty. Sandbox nenahrazuje správně nastavené permissions a kontrolu citlivých operací.
Spuštění skutečně nedůvěryhodného kódu Jednorázové nebo omezené prostředí bez SSH klíčů, produkčních tokenů, cloud credentials, hostitelského Docker socketu a dalších nepotřebných dat. Omezuje dopad, pokud se škodlivý kód skutečně spustí. Nezabrání samotnému spuštění škodlivého programu.
Docker Nepředávat nedůvěryhodnému containeru Docker socket; hostitelské mounty omezit a podle potřeby použít read-only. Docker socket poskytuje velmi silná oprávnění a zapisovatelný bind mount umožňuje měnit hostitelské soubory. Container sám o sobě není úplná bezpečnostní hranice.
Git a okolní tooling Udržovat podporovanou aktuální verzi přes běžný update mechanismus používaného systému. Git, package managery, editory i runtime mají vlastní bezpečnostní chyby. Aktualizace nechrání před legitimní funkcí, kterou škodlivý projekt použije přesně podle návrhu.

Kolik důvěry projekt skutečně potřebuje?

U cizího repozitáře není potřeba rozhodnout jednou provždy, jestli je „bezpečný“ nebo „nebezpečný“.

Praktičtější je rozhodovat postupně.

Pro přečtení zdrojových souborů nepotřebuje projekt přístup k SSH klíčům. Pro instalaci závislostí nemusí být nutné automaticky spustit všechny install skripty. Coding agent, který má vysvětlit architekturu, nemusí mít automaticky právo spouštět libovolný software. A projekt, který potřebujete opravdu rozběhnout, nemusí běžet pod stejným účtem a se stejnými credentials jako vaše běžná práce.

Čím méně důvěry konkrétní krok potřebuje, tím méně jí má smysl projektu dávat.

Řešíte bezpečnost konkrétního vývojového prostředí, CI nebo coding agentů?

Pokud potřebujete posoudit konkrétní workflow, oprávnění nebo bezpečnostní návrh, můžeme ho projít v rámci Bezpečnostní konzultace. Cílem je dojít ke konkrétnímu doporučení pro vaše prostředí, ne vyrábět zbytečně široký audit.


Zdroje


Visual Portfolio, Posts & Image Gallery for WordPress

Infra Audit

Audit infrastruktury se zaměřením na bezpečnost a soukromí.

Firemní školení

Školení pro zaměstnance může výrazně snížit riziko hackerského útoku na vaši firmu