Każde zadanie GitHub Actions dostaje token. GitHub tworzy nowy GITHUB_TOKEN na początku każdego zadania, z zakresem ograniczonym do repozytorium, w którym znajduje się workflow, a każdy krok zadania może go użyć. To, co token może zrobić, zależy od ustawień, na które wiele zespołów nigdy nie spojrzało, a w starszych repozytoriach odpowiedź wciąż brzmi: zapisywać niemal wszędzie.
Ma to znaczenie, gdy coś w zadaniu okazuje się złośliwe. Podczas ataku „s1ngularity” na Nx w sierpniu 2025 roku token repozytorium nadal miał uprawnienia do odczytu i zapisu. Wstrzyknięcie w workflow pull_request_target użyło go do uruchomienia workflow publikującego, co ujawniło token npm użyty do opublikowania złośliwych wersji Nx. Token tylko do odczytu zatrzymałby ten krok.
W tym wpisie omawiamy, jak ustawia się uprawnienia tokenu, czego potrzebuje każde typowe zadanie i jak znaleźć minimum dla Państwa workflowów.
Czym jest GITHUB_TOKEN
GITHUB_TOKEN to token dostępu instalacji aplikacji GitHub Actions. Kilka jego właściwości łatwo przeoczyć:
- Istnieje niezależnie od tego, czy jest używany. Workflowy odwołują się do niego jako
secrets.GITHUB_TOKEN, ale każda akcja może go odczytać przez kontekstgithub.token, nawet jeśli nikt jej go nie przekazał. - Domyślnie jest zapisywany na dysku.
actions/checkoutzachowuje token na potrzeby późniejszych poleceń git, chyba że ustawią Państwopersist-credentials: false. Przed wersją v6 trafiał do.git/config; wersja v6 przeniosła go do osobnego pliku w$RUNNER_TEMP. W 2024 roku badanie ArtiPACKED zespołu Unit 42 wykryło wycieki tokenów przez artefakty zawierające.git/config. - Wygasa wraz z zadaniem. Na runnerach hostowanych przez GitHub oznacza to najwyżej 6 godzin, czyli limit czasu zadania. Na runnerach self-hosted może być odświeżany do 24 godzin.
Ponieważ token jest zawsze obecny, kontrolować można tylko to, ile może zrobić.
Ustawienie domyślne: permissive lub restricted
Każde przedsiębiorstwo, organizacja i repozytorium ma ustawienie domyślne dla tokenu:
- Permissive: odczyt i zapis dla każdego uprawnienia.
- Restricted: tylko odczyt dla
contentsipackages, poza tym nic.
Od 2 lutego 2023 roku nowe przedsiębiorstwa, organizacje i repozytoria mają domyślnie ustawienie restricted. Zmiana nie objęła istniejących, więc każde repozytorium lub organizacja utworzona wcześniej zachowuje ustawienie permissive, o ile nikt go nie zmienił. Jeśli wyższy poziom wybierze restricted, niższe nie mogą wybrać permissive.
Można to sprawdzić w Settings → Actions → General → Workflow permissions, najpierw na poziomie organizacji. W tej samej sekcji znajduje się opcja Allow GitHub Actions to create and approve pull requests, która powinna pozostać wyłączona, chyba że workflow jej potrzebuje.
Klucz permissions
Klucz permissions w workflow dostosowuje token względem ustawienia domyślnego. Działa na dwóch poziomach:
permissions:
contents: read
jobs:
release:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<full-commit-sha>
Zasady:
- Poziom zadania nadpisuje poziom workflow. Domyślnie dla workflow należy ustawić tylko odczyt, a uprawnienia podnosić wyłącznie w zadaniach, które tego wymagają.
- Wszystko, czego Państwo nie wymienią, staje się
none. Gdy tylko ustawią Państwo jedno uprawnienie, wszystkie pozostałe zostają usunięte.permissions: {}usuwa je wszystkie. - Wartości to
read,writelubnone.writeobejmujeread.read-alliwrite-allustawiają wszystko naraz;write-allnależy unikać.
Dostępne uprawnienia według stanu na wrzesień 2026 roku:
| Uprawnienie | Co kontroluje |
|---|---|
actions | Uruchomienia workflowów, artefakty i cache |
artifact-metadata | Rekordy metadanych artefaktów (w 2026 zastąpiło contents dla tych API) |
attestations | Atestacje artefaktów |
checks | Uruchomienia i zestawy checków |
code-quality | Wyniki jakości kodu, takie jak raporty pokrycia |
contents | Zawartość repozytorium, commity, gałęzie, tagi i wydania |
deployments | Wdrożenia |
discussions | Dyskusje |
id-token | Żądanie tokenu OIDC (tylko write lub none) |
issues | Zgłoszenia i komentarze |
packages | GitHub Packages, łącznie z rejestrem kontenerów |
pages | Buildy GitHub Pages |
pull-requests | Pull requesty, etykiety i recenzje |
security-events | Alerty code scanning i wysyłanie SARIF |
statuses | Statusy commitów |
vulnerability-alerts | Alerty Dependabot (tylko read lub none) |
Gdy zadaniu brakuje potrzebnego uprawnienia, wywołanie API kończy się błędem 403 Resource not accessible by integration. Ten błąd to sygnał, by dodać jedno uprawnienie potrzebne w danym kroku, a nie by przejść na write-all.
Czego potrzebują typowe zadania
| Zadanie | Uprawnienia |
|---|---|
| Pobranie kodu | contents: read |
| Utworzenie wydania lub wypchnięcie tagu | contents: write |
| Komentarz do zgłoszenia lub pull requesta | issues: write (komentarze do pull requestów przechodzą przez API zgłoszeń) |
| Dodanie etykiet lub recenzji do pull requesta | pull-requests: write |
| Uwierzytelnienie u dostawcy chmury przez OIDC | id-token: write |
| Tworzenie atestacji artefaktów | id-token: write, attestations: write, contents: read, a dla obrazów kontenerów także packages: write |
| Wypchnięcie obrazu do GitHub Container Registry | packages: write |
| Wysłanie SARIF do code scanning | security-events: write |
| Wdrożenie GitHub Pages z workflow | pages: write, id-token: write |
Większość zadań testowych i buildów nie potrzebuje niczego poza contents: read.
Forki, pull_request_target i Dependabot
- Pull requesty z forków dostają na zdarzeniu
pull_requesttoken tylko do odczytu, niezależnie od tego, o co prosi workflow, chyba że administrator włączy opcję „Send write tokens to workflows from pull requests”. Należy pozostawić ją wyłączoną. pull_request_targetdostaje token do odczytu i zapisu nawet dla pull requestów z publicznych forków. Dlatego stoi za wieloma najbardziej znanymi kradzieżami tokenów: atak na Nx, atak na Ultralytics w grudniu 2024 roku i atak na akcję Trivy w marcu 2026 roku zaczęły się od workflowpull_request_target. GitHub to zawęża: od lipca 2026 rokuactions/checkoutdomyślnie odmawia pobrania kodu z forka w takich workflowach, a od 2 listopada 2026 roku repozytoria publiczne bez własnej polityki będą miałypull_request_targetdomyślnie wyłączony.- Pull requesty Dependabota są traktowane jak forki: token tylko do odczytu i brak sekretów Actions. Osoby rozważające inne narzędzia do aktualizacji zapraszamy do lektury o alternatywach dla Dependabota.
Jak znaleźć minimalne uprawnienia
Nie trzeba ustalać tego przez czytanie kodu źródłowego każdej akcji:
- actions-permissions z GitHub Security Lab monitoruje, jak workflow używa tokenu, i zaleca minimalne uprawnienia. Jest w publicznej wersji beta.
- Test Token-Permissions w OpenSSF Scorecard oznacza workflowy, które nie ustawiają uprawnień tylko do odczytu na najwyższym poziomie. Przypisuje temu testowi wysoki poziom ryzyka.
- zizmor, analizator statyczny workflowów, oznacza nadmierne lub domyślne uprawnienia oraz checkouty zachowujące poświadczenia.
- Secure-Repo i Harden-Runner firmy StepSecurity zalecają uprawnienia na poziomie zadania na podstawie bazy wiedzy o akcjach i wywołań API wykonywanych przez zadanie.
Praktyczne wdrożenie: ustawić domyślnie restricted dla organizacji, dodać permissions: contents: read na początku każdego workflow i uruchomić workflowy. Te, które zakończą się błędem Resource not accessible by integration, wskażą dokładnie, które zadanie potrzebuje którego dodatkowego uprawnienia.
Gdzie pasuje CRACI
Najmniejsze uprawnienia ograniczają to, co może zrobić skradziony token. Nie chronią przed samą kradzieżą, a pozostałe sekrety w zadaniu, takie jak tokeny npm i poświadczenia chmurowe, są tak samo narażone.
CRACI uruchamia Państwa zadania GitHub Actions na własnych runnerach. Wystarczy zmienić runs-on na craci; GITHUB_TOKEN, klucz permissions i ustawienia repozytorium działają jak dotąd, ponieważ token nadal wydaje GitHub. CRACI dodaje coś na poziomie runnera: politykę egress, która decyduje, z którymi hostami zadanie może się łączyć, jest walidowana przed startem zadania i w razie awarii blokuje ruch (fail closed), oraz zapis każdego pakietu pobranego przez zadanie wraz ze śladem jego połączeń sieciowych. Jeśli złośliwy kod w zadaniu zdobędzie token, polityka ogranicza, dokąd może go wysłać, a zapis pokazuje, co się stało.
O pozostałych sekretach zadania przeczytają Państwo w artykule Sekrety GitHub Actions: jak wyciekają i jak je zabezpieczyć. Prosimy umówić demo, aby zobaczyć zapis jednego z Państwa buildów.
