Firma si nechá udělat bezpečnostní audit, opraví nálezy a má pocit, že je hotovo. Za tři měsíce vývojář spustí rutinní aktualizaci závislostí, protože přibyla nová verze jedné knihovny. Aplikace se sestaví, testy projdou, nasazení proběhne. A spolu s ním se do produkce dostane kód, který nikdo z týmu nenapsal, nečetl a ani si ho nevšiml.
Tohle není hypotetický scénář, je to nejrychleji rostoucí způsob, jak se dnes útočí na software. A je nepříjemný přesně tím, že obchází všechno, do čeho firmy bezpečnostní rozpočet obvykle dávají.
Kolik cizího kódu doopravdy máte v projektu
Začněme čísly, která si můžete ověřit sami. Vzal jsem web, na kterém tenhle článek čtete. Je to poměrně střídmý projekt: Next.js, pár komponent, obsah v souborech, žádná exotika.
V package.json má 18 přímých závislostí. Tedy 18 knihoven, které jsme vybrali vědomě a u kterých bychom dokázali vysvětlit proč.
Po instalaci je ve složce node_modules 298 balíčků.
Rozdíl je 280 balíčků, které si přitáhly ty naše. Závislosti závislostí, o několik pater hlouběji. Nikdo z nás je nevybral, u většiny z nich netušíme jméno autora a u řady z nich jde o projekty, které ve volném čase spravuje jeden člověk.
A ještě jedno číslo. Tři z těch balíčků mají takzvaný instalační skript, tedy kód, který se spustí automaticky už při npm install. Ne až když aplikaci pustíte. Při instalaci.
U větších aplikací ta čísla rostou. Běžná firemní aplikace s administrací, platbami a napojením na okolní systémy se dostane přes tisíc balíčků. Váš tým jich napsal pár tisíc řádků. Nainstaloval několik milionů.
Jak takový útok vypadá v praxi
Útok na dodavatelský řetězecÚtok, který necílí na vaši aplikaci, ale na některou z knihoven, nástrojů nebo služeb, ze kterých je poskládaná. Škodlivý kód se do vašeho projektu dostane běžnou aktualizací závislosti.Celá definice → má obvykle jeden ze tří scénářů. U všech tří existují konkrétní, dobře zdokumentované případy.
Útočník převezme opuštěný balíček
Případ event-stream z roku 2018 je učebnicový. Autor populární knihovny ji přestal používat a už ho nebavilo ji udržovat. Ozval se dobrovolník, že projekt rád převezme. Autor mu ho předal, což je v open source běžná a vlastně sympatická věc.
Nový správce pak přidal další závislost, která obsahovala zašifrovaný škodlivý kód. Ten se aktivoval jen v jediném prostředí: v konkrétní bitcoinové peněžence, kde kradl privátní klíče. Knihovna měla v té době miliony stažení týdně. Cíl byl jeden.
Útočník se zmocní účtu správce
V roce 2021 se útočníci dostali k účtu autora knihovny ua-parser-js a vydali pod jeho jménem verze s těžbou kryptoměn a nástrojem na krádež hesel. Balíček je závislostí obrovského množství projektů, takže se zásah během hodin rozlil do velké části ekosystému, než se stihly vydat opravné verze.
Loni v září prošla npm vlna phishingu mířeného přímo na správce velmi populárních balíčků. Útočníci tak dostali škodlivý kód do knihoven se stovkami milionů stažení týdně. Součástí téže vlny byl i škodlivý kód, který se choval jako červ: z napadeného projektu si vzal přístupové tokeny a pomocí nich sám publikoval další zasažené balíčky.
Útočník si důvěru trpělivě vybuduje
Nejznámějším případem je backdoor v XZ Utils (CVE-2024-3094) z března 2024. Člověk vystupující pod jménem Jia Tan přispíval do projektu komprimační knihovny bezmála dva roky. Psal užitečný kód, byl ochotný a vstřícný, pomáhal vyčerpanému původnímu správci. Postupně získal právo vydávat nové verze.
Pak do vydaných balíčků propašoval kód, který se v git repozitáři vůbec nenacházel, a který na napadeném serveru otevíral zadní vrátka do SSH. Útok mířil na servery po celém světě a byl velmi blízko tomu, aby se dostal do stabilních verzí velkých linuxových distribucí.
Odhalil ho inženýr, který zkoumal, proč mu přihlášení přes SSH trvá o půl sekundy déle než obvykle. Ne bezpečnostní nástroj, ne audit, ne certifikace. Náhoda a všímavost jednoho člověka.
Proč to neodhalí revize kódu ani penetrační test
Tohle je ta část, která bývá pro rozhodování o rozpočtu nejdůležitější, protože vysvětluje, proč vám dosavadní opatření nestačí.
Revize kódu prochází změny, které napsal váš tým. Aktualizace závislosti se v ní projeví jako změna dvou čísel v zamykacím souboru. Nikdo nečte diff o padesáti tisících řádcích cizího kódu, a kdyby chtěl, nestihne to.
Penetrační test zkouší aplikaci, která v danou chvíli běží. Když se škodlivá verze objeví o měsíc později, test o ní neví. Testujeme stav, ne budoucnost. Pět zranitelností, na které při testech narážíme nejčastěji, popisuje samostatný článek a ani jedna z nich není tohohle druhu.
Automatické skenování zranitelností (Dependabot, Snyk) hlásí známé chyby, tedy ty, které už někdo objevil, nahlásil a zařadil do databáze. Cílený útok je z definice nový. Ve chvíli, kdy se škodlivá verze objeví v databázi, ji máte v produkci už několik dní.
A konečně: čím víc kódu generuje AI, tím rychleji závislosti přibývají a tím míň jich někdo vybral s rozmyslem. Podrobněji to rozebírá článek o bezpečnosti AI-generovaných aplikací.
Co s tím jde dělat
Dobrá zpráva je, že obrana není drahá. Je to sada nastavení, ne nová položka v rozpočtu. Seřazeno podle toho, kolik přinese za vynaložené úsilí:
- Odložte instalaci nových verzí o dva dny. Nejúčinnější jednotlivé opatření. Škodlivé balíčky bývají odhaleny a z registru staženy během prvních hodin až dnů, takže projekt, který nikdy neinstaluje verzi mladší než 48 hodin, většinu vln prostě mine. Správci balíčků to dnes umí zapnout jedním řádkem v konfiguraci.
- Zamykací soubor je závazný. V CI se instaluje přes
npm ci, nenpm install. Sestavení se pak nikdy nespustí na verzi, kterou nikdo neschválil. - Vypněte instalační skripty tam, kde nejsou potřeba. Instalace s
--ignore-scriptsa výslovný seznam výjimek pro balíčky, které to opravdu vyžadují (u nás jsou tři). Zavírá to nejčastěji zneužívanou cestu. - Omezte, kam smí sestavovací linka volat. Škodlivý kód potřebuje odeslat, co ukradl. Když stroj, který sestavuje aplikaci, nemá volný přístup do internetu, útok skončí bez výsledku.
- Držte inventář komponent (SBOM). Strojově čitelný seznam všeho, co v aplikaci je. V den, kdy vyjde najevo další případ, je rozdíl mezi „za deset minut víme, jestli se nás to týká“ a dvěma dny hledání.
- Aktualizujte pravidelně, ne nárazově. Projekt, který se neaktualizoval rok, nedokáže rychle uniknout, až bude potřeba. Nejde jen o to nestahovat novinky hned, ale umět se pohnout, když je nutné.
- Snižte počet závislostí. Nejlevnější balíček je ten, který v projektu není. U každé nové knihovny stojí za otázku, jestli ušetřené dva dny práce stojí za dalších třicet balíčků pod ní.
Ve vlastních projektech tohle nastavujeme hned na začátku, ne až po auditu. Zabere to jedno odpoledne a od té chvíle se to stará samo.
Kolik z toho dává smysl u vás
Ne každá firma potřebuje všech sedm bodů, a právě proto bývá tenhle rozhovor s dodavatelem užitečný.
Pokud provozujete běžnou firemní aplikaci, vystačíte si s prvními třemi body. Jsou zdarma, zaberou jedno odpoledne a pokryjí drtivou většinu reálných útoků.
Pokud pracujete s citlivými daty, platbami nebo zdravotními údaji, přidejte omezení sítě v sestavovací lince a inventář komponent. Náklad je v řádu člověkodnů, jednorázově.
A pokud spadáte pod NIS2Evropská směrnice o kybernetické bezpečnosti. V Česku ji zavádí stejnojmenný zákon, který dopadá na výrazně širší okruh organizací než dřív, včetně běžných webových aplikací a jejich dodavatelů.Celá definice →, nemáte na vybranou: bezpečnost dodavatelského řetězce včetně SBOM a ověřování integrity závislostí je výslovná povinnost, kterou musíte umět doložit. Co všechno regulace vyžaduje, rozebírá průvodce NIS2 pro webové aplikace.
Argument, proč to není zbytečně vyhozený rozpočet, je nakonec jednoduchý. Nekupujete si ochranu před něčím vzdáleným. Kupujete si to, že když příště praskne další případ (a praskne, tempo posledních let je jednoznačné), nebudete dva dny zjišťovat, jestli se vás to týká.
Nejčastější dotazy
Časté otázky
Nestačí používat jen velké a populární knihovny?
Nestačí. Popularita je pro útočníka důvod, proč si balíček vybrat, ne záruka bezpečí. Největší případy posledních let se týkaly právě knihoven se stovkami milionů stažení týdně.
Pomůže, když závislosti vůbec nebudeme aktualizovat?
Nepomůže, spíš naopak. Zmrazený projekt sice neinstaluje škodlivé novinky, ale hromadí známé zranitelnosti a v okamžiku, kdy je potřeba se rychle pohnout, to nejde. Správná odpověď je aktualizovat pravidelně, jen ne okamžitě po vydání.
Jak poznáme, že se nás nějaký zveřejněný případ týká?
Z inventáře komponent, tedy SBOM. Bez něj to znamená procházet instalace jednotlivých projektů ručně. S ním je to dotaz na pár minut.
Týká se to i projektů, které nepoužívají npm?
Ano. Ekosystém JavaScriptu je nejčastěji zasažený, protože je největší, ale stejné útoky proběhly i v Pythonu, Rustu a u systémových knihoven Linuxu. Princip je všude stejný.
Nevíte, kolik cizího kódu máte v aplikaci a co se s ním děje při každém nasazení? Ve Softero děláme vývoj softwaru na míru i bezpečnostní audity existujících projektů, včetně revize závislostí a nastavení ochran popsaných výše. Ozvěte se nám a projdeme to na vašem projektu.

