TL;DR
- 11 września 2026 wszedł w życie pierwszy kluczowy obowiązek z CRA: zgłoszenie aktywnie wykorzystywanej podatności w ciągu 24 godzin od uzyskania wiedzy. Większość pozostałych obowiązków zacznie obowiązywać 11 grudnia 2027.
- Z Annex I zostają cztery obowiązki techniczne, które da się zautomatyzować: SBOM, skan zależności przy każdym pull requeście, cykliczny skan tego, co działa u klientów, i osobny alert dla podatności z exploitem.
- Na Jenkinsie załatwia to wtyczka vuln-today-jenkins-plugin i jedna linijka w Jenkinsfile:
vulnScan file: 'package-lock.json'. - Lockfile i sbom.cdx.json w repozytorium to dokumentacja komponentów każdej wersji. Git pamięta historię, więc pytanie „co było w wersji z marca” to jedna komenda.
- Pipeline nie zastąpi polityki skoordynowanego ujawniania, pliku security.txt ani osoby, która po alercie ocenia, czy to zgłoszenie do CSIRT.
Zanim prawnicy się obudzą
11 września 2026 wszedł w życie pierwszy kluczowy obowiązek z CRA, czyli obowiązek zgłaszania aktywnie wykorzystywanych podatności w ciągu 24 godzin. Prędzej czy później ktoś z działu prawnego przyjdzie do zespołu z trzema pytaniami: jakie komponenty są w wersji produktu, którą klienci mają dziś (i którą mieli rok temu), czy któryś z nich ma znaną, wykorzystywaną podatność, i kto o tym wie.
Dobra wiadomość: na wszystkie trzy pytania może odpowiadać pipeline. Poniżej pokazujemy, jak zrobiliśmy to na Jenkinsie z vuln.today, polskim narzędziem do analizy podatności stworzonym przez naszego inżyniera bezpieczeństwa.
Czego CRA wymaga od twórców oprogramowania
Rozporządzenie weszło w życie 10 grudnia 2024. Większość obowiązków zaczyna obowiązywać 11 grudnia 2027, ale raportowanie podatności i incydentów (art. 14) wystartowało już 11 września 2026. Producent, który dowiaduje się, że podatność w jego produkcie jest aktywnie wykorzystywana, zgłasza to do ENISA i krajowego CSIRT przez nową platformę raportowania.
Zgłoszenie ma trzy etapy:
- wczesne ostrzeżenie w 24 godziny od uzyskania wiedzy (co i w jakim produkcie),
- pełniejsze powiadomienie w 72 godziny (charakter podatności i exploita, podjęte lub dostępne środki zaradcze),
- raport końcowy 14 dni po udostępnieniu poprawki.
Niezależnie od zgłoszenia producent informuje klientów, których ta konkretna podatność dotyczy, o problemie i dostępnych środkach zaradczych. Uspokajamy: nie chodzi o publiczny komunikat o CVE w zależnościach. Obowiązek dotyczy tylko podatności aktywnie wykorzystywanej w Waszym produkcie, a wytyczne Komisji pozwalają ograniczyć szczegóły do dotkniętych klientów, gdy publiczne ujawnienie zwiększałoby ryzyko. Nie chcemy przecież podawać atakującym informacji o podatnościach w naszych produktach. Co istotne, obowiązek obejmuje też produkty wprowadzone na rynek przed 11 grudnia 2027.
24 godziny na wczesne ostrzeżenie od uzyskania wiedzy o aktywnie wykorzystywanej podatności. Potem 72 godziny na powiadomienie i 14 dni po udostępnieniu poprawki na raport końcowy.
Annex I część II opisuje, w jaki sposób producent ma obsługiwać podatności. Po odfiltrowaniu obowiązków czysto procesowych (polityka CVD, kontakt do zgłaszania, publikowanie advisory) zostają cztery, które można i warto zautomatyzować.
Cztery wymagania, które warto zautomatyzować
| Wymóg CRA | Co to technicznie znaczy | Jak to robimy |
|---|---|---|
| SBOM w formacie maszynowo czytelnym, co najmniej zależności najwyższego poziomu, przechowywany z dokumentacją techniczną | Spis komponentów dla każdej wersji, która była u klientów, dostępny na żądanie przez lata | Lockfile i SBOM w repozytorium, historia w git |
| Identyfikować i dokumentować podatności w komponentach | Skan drzewa zależności | Skan lockfile przy każdym pull requeście |
| Regularnie testować i przeglądać bezpieczeństwo produktu | Skan tego, co jest wdrożone, bez czekania na zmianę w kodzie | Skan dzienny gałęzi lub tagu produkcyjnego |
| Zgłaszać aktywnie wykorzystywane podatności w 24 godziny (art. 14) | Sygnał KEV lub exploit musi natychmiast trafić do konkretnej osoby | Osobny kanał Slack dla podatności z exploitem |
Zanim ktoś zamknie tekst z myślą „ale my przecież tworzymy SaaS, to nas nie dotyczy”: CRA obejmuje produkty udostępniane na rynku, czyli oprogramowanie dostarczane klientowi. Czysty SaaS co do zasady podlega NIS2, a nie CRA. Ale aplikacja mobilna, biblioteka, wtyczka, agent czy instalacja on-prem dla takiego produktu - już tak. Wiele firm ma w portfolio przynajmniej jedną taką rzecz, a wymagania wobec zależności są pod NIS2 identyczne.
Wdrożenie na Jenkinsie
Całość opiera się na naszej wtyczce do Jenkinsa vuln-today-jenkins-plugin (kod na GitHubie) i API vuln.today. Wtyczka dodaje krok vulnScan, który wysyła wskazany lockfile do API, odbiera listę podatności i wysyła powiadomienia. Sam skan wykonuje się na agencie, na którym działa build. Wtyczka powstała w duchu minimalizmu: na agentach nie trzeba instalować żadnych skanerów, curl ani jq, a kontroler Jenkinsa nie przetwarza plików z repozytoriów. Na kontrolerze zostaje tylko to, co powinno się tam znajdować: credentiale i stan powiadomień, czyli które CVE zostały już zgłoszone dla której aplikacji i wersji, żeby nie generować duplikatów.
Jednorazowa konfiguracja:
- Instalacja wtyczki (
.hpi) w Manage Jenkins, Plugins. - Dwa credentiale typu Secret text:
vuln-today-api-keyivuln-today-slack-webhook. Opcjonalnie trzeci,vuln-today-slack-webhook-critical, dla kanału, na który trafiają podatności z exploitem.
Potem w każdym projekcie jedna linijka:
pipeline {
agent any
stages {
stage('Dependency Scan') {
when { changeRequest() }
steps {
vulnScan file: 'package-lock.json'
}
}
}
}
Podajemy ścieżkę do lockfile i nic więcej. vuln.today samo rozpoznaje format (npm, Composer, pip, Go, Maven, Gradle, Cargo, Bundler, a także SBOM w CycloneDX i SPDX). Wynik wraca w kilka sekund, wtyczka agreguje go per paczka i wysyła powiadomienie. To pokrywa drugi wymóg: każda zmiana zależności jest sprawdzona, zanim trafi do gałęzi głównej.
SBOM: jedno źródło prawdy, czyli repozytorium
Pierwszy wymóg jest w większości spełniony, zanim cokolwiek zrobimy. Plik package-lock.json to maszynowo czytelny spis wszystkich komponentów, łącznie z zależnościami przechodnimi, wersjami i sumami kontrolnymi. Leży w repozytorium, a git pamięta każdą jego wersję. Pytanie organu nadzoru „co było w wersji wdrożonej w marcu 2027” to zwykła komenda git show <commit>:package-lock.json. Nie potrzeba do tego tagów, osobnego artefaktu ani zewnętrznego narzędzia. Wystarczy git.
SBOM jest wymieniony wprost w Annex VII jako element dokumentacji technicznej, a tę producent powinien przechowywać przez 10 lat od wprowadzenia produktu na rynek albo przez okres wsparcia, jeśli jest dłuższy. W praktyce sprowadza się to do nieusuwania repozytorium.
Jedna rzecz jest na ten moment niepewna: rozporządzenie mówi o „powszechnie używanym formacie”, a Komisja może go doprecyzować aktem wykonawczym. Takiego aktu na dziś nie ma. Najczęściej przywoływanym punktem odniesienia jest niemiecka wytyczna BSI TR-03183-2 wskazująca CycloneDX lub SPDX i nie wiadomo, czy lockfile npm zostanie uznany za wystarczający. Dlatego obok lockfile trzymamy w repozytorium sbom.cdx.json, generowany w pipeline na gałęzi głównej i commitowany, gdy się zmienił:
stage('SBOM') {
when { branch 'master' }
steps {
sh '''
npm sbom --sbom-format cyclonedx --omit dev > sbom.cdx.json
git diff --quiet sbom.cdx.json || {
git commit -m "chore: update SBOM [skip ci]" sbom.cdx.json
git push origin HEAD:master
}
'''
}
}
Komenda npm sbom jest wbudowana w npm od wersji 9.5, a dla Composera (PHP) jest cyclonedx-php-composer. SBOM żyje obok lockfile, ma tę samą historię i ten sam commit co kod, który opisuje. Deweloper nie musi pamiętać ani o nim, ani o jego generowaniu.
Skan dzienny tego, co jest wdrożone
To trzeci wymóg. Nowe CVE nie czekają na pull request: produkt, którego nikt nie dotykał od pół roku, może dostać CVE z exploitem dziś. Dlatego skan dzienny musi dotyczyć tego, co faktycznie działa u klientów, a nie tego, co dopiero wydamy albo właśnie wydaliśmy. Innymi słowy nie wystarczy zeskanować oprogramowania raz przy wydaniu i zapomnieć. Trzeba je skanować cyklicznie.
W większości projektów produkcja to ostatni build gałęzi głównej. W takim wypadku wystarczy job z cronem na tej gałęzi:
pipeline {
agent any
triggers { cron('H 6 * * *') }
stages {
stage('Scan deployed release') {
steps {
vulnScan file: 'package-lock.json'
}
}
}
}
Jeśli klienci on-prem siedzą na starszej wersji albo utrzymujecie kilka linii wsparcia, ten sam job robi checkout odpowiedniego tagu i wywołuje vulnScan file: 'package-lock.json', version: TAG. Parametr version daje osobny stan każdej wersji: to samo CVE naprawione w 3.0.0 nadal wraca jako otwarte dla 2.3.1, zamiast zniknąć w deduplikacji.
Alert, który rozróżnia „zaktualizować” od „zgłosić”
Czwarty wymóg, najważniejszy od 11 września. Obowiązek zgłoszenia dotyczy podatności aktywnie wykorzystywanej, a nie każdej z wysokim CVSS. CVE 9.8 bez znanego exploita to pilna aktualizacja. CVE 6.5 z katalogu CISA KEV, w wersji, którą klient ma na produkcji, to potencjalnie start 24-godzinnego zegara. Gdyby oba wyglądały na Slacku tak samo, to drugie utonęłoby w środku listy, bo ma niższy wynik, a w praktyce jest ważniejsze pod względem prawnym.
vuln.today zwraca przy każdej podatności nie tylko CVSS, ale też epss_score, flagę kev (CISA Known Exploited Vulnerabilities) i flagę poc (publicznie dostępny exploit). Wtyczka rozdziela na tej podstawie powiadomienia na dwie klasy:
- Nowe CVE w zależnościach: kanał zespołu, paczki posortowane po CVSS, wersja naprawiona, gotowa komenda
npm install, linki. To samo CVE może wrócić po 7 dniach jako przypomnienie. - Podatność wykorzystywana lub z exploitem (
kev == truealbopoc == true): osobny kanał, bez deduplikacji, z nazwą wersji i wzmianką osoby odpowiedzialnej za ocenę.
Drugi alert nie jest jeszcze zgłoszeniem. Fakt, że biblioteka ma publiczny exploit, nie znaczy automatycznie, że nasz produkt jest podatny: może nie używać tej funkcji, może mieć mitygację. Ale to jest moment, w którym ktoś musi tej oceny dokonać i ją udokumentować. Wytyczne Komisji mówią wprost: producent „uzyskuje wiedzę” dopiero wtedy, gdy po wstępnej ocenie ma uzasadnioną pewność, że podatność w jego produkcie jest aktywnie wykorzystywana. Tę wstępną ocenę ma jednak wykonać niezwłocznie.
Czego pipeline nie załatwi
Pipeline odpowiada na pytania „co mamy” i „co jest podatne”. Trzy rzeczy z Annex I są poza zasięgiem skanera:
- publiczny kontakt do zgłaszania podatności (
/.well-known/security.txt) i polityka skoordynowanego ujawniania, - szablon advisory i miejsce, w którym publikujecie informacje o usuniętych podatnościach (Annex I cz. II pkt 4 wymaga tego dopiero po udostępnieniu poprawki, więc to zwykłe security release notes, a nie ostrzeżenie przed łatką),
- wyznaczona osoba, która po alercie z kanału krytycznego ocenia, czy to zgłoszenie do CSIRT, i miejsce, w którym zapisuje uzasadnienie.
Wyznaczona osoba jest ogniwem między pipeline a prawnikami. Wskazujemy ją po to, aby w dniu, w którym zegar ruszy naprawdę, nikt nie pytał „kto się tym zajmuje?”.
Podsumowanie
Cztery obowiązki techniczne z CRA to jedna wtyczka i kilka linijek w Jenkinsfile:
vulnScanna pull requestach: żadna podatna zależność nie wchodzi do gałęzi głównej niezauważona.vulnScancyklicznie na gałęzi lub tagu produkcyjnym: wdrożone wersje są sprawdzane wobec CVE opublikowanych wczoraj.- Lockfile i
sbom.cdx.jsonw repozytorium: dokumentacja komponentów każdej wersji, z historią w git, u samego źródła. - Oddzielne kanały Slack: aktualizacje osobno, potencjalne zgłoszenia osobno, z odpowiedzialną osobą.
Niezależnie od tego, czy skanujecie przez vuln.today, Trivy, Grype czy OSV-Scanner i czy raportujecie na Slacku czy Mattermost, warto sprawdzić u siebie te same cztery rzeczy: czy skan widzi lockfile, a nie manifest; czy uruchamia się bez zmiany w kodzie; czy dotyczy wersji, które klienci mają; i czy sygnał „exploit dostępny” wygląda inaczej niż zwykłe CVE. Jeśli tak, prawnicy mogą się obudzić, kiedy tylko chcą. Odpowiedzi będą na nich czekać w repozytorium i w Jenkinsie.
Źródła
- Rozporządzenie (UE) 2024/2847 (Cyber Resilience Act), tekst w EUR-Lex: eur-lex.europa.eu
- CRA, art. 13: obowiązki producentów, w tym SBOM i dokumentacja techniczna
- CRA, art. 14: obowiązki raportowe producentów
- CRA, art. 71: wejście w życie i stosowanie
- CRA, Annex VII: zawartość dokumentacji technicznej
- Komisja Europejska: wytyczne do stosowania CRA, C(2026) 5252, 27 lipca 2026
- ENISA: Single Reporting Platform: enisa.europa.eu
- BSI TR-03183-2: wymagania dla SBOM
- npm sbom, dokumentacja: docs.npmjs.com
- cyclonedx-php-composer: github.com
- Wtyczka vuln-today-jenkins-plugin, kod źródłowy: github.com/radeksh/vuln-today-jenkins-plugin
- vuln.today: vuln.today