Gh Actions - Context Script Injections
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
Zrozumienie ryzyka
GitHub Actions renderuje wyrażenia ${{ … }} zanim krok się wykona. Wartość po renderowaniu jest wklejana do programu kroku (dla kroków z run:, skrypt shell). Jeśli interpolujesz niezaufane dane bezpośrednio w run:, atakujący kontroluje część programu shell i może wykonać dowolne polecenia.
Dokumentacja: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions and contexts/functions: https://docs.github.com/en/actions/learn-github-actions/contexts
Kluczowe punkty:
- Renderowanie odbywa się przed wykonaniem. Skrypt z run: jest wygenerowany z wszystkimi rozwiązanymi wyrażeniami, a następnie wykonany przez shell.
- Wiele contexts zawiera pola kontrolowane przez użytkownika w zależności od zdarzenia wyzwalającego (issues, PRs, comments, discussions, forks, stars, etc.). Zobacz untrusted input reference: https://securitylab.github.com/resources/github-actions-untrusted-input/
- Cytowanie w shellu wewnątrz run: nie jest niezawodną obroną, ponieważ wstrzyknięcie ma miejsce na etapie renderowania szablonu. Atakujący mogą wyłamać się z cytatów lub wstrzyknąć operatory za pomocą spreparowanego inputu.
Wrażliwy wzorzec → RCE na runnerze
Wrażliwy workflow (wyzwalany, gdy ktoś otwiera nowe issue):
name: New Issue Created
on:
issues:
types: [opened]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: New issue
run: |
echo "New issue ${{ github.event.issue.title }} created"
- name: Add "new" label to issue
uses: actions-ecosystem/action-add-labels@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
labels: new
Jeśli atakujący otworzy issue zatytułowane $(id), wyrenderowany krok staje się:
echo "New issue $(id) created"
Substytucja polecenia uruchamia id na runnerze. Przykładowe wyjście:
New issue uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),100(users),999(systemd-journal) created
Dlaczego cytowanie nie wystarczy:
- Wyrażenia są najpierw renderowane, a następnie uruchamiany jest otrzymany skrypt. Jeśli niezaufana wartość zawiera $(…),
;,"/'lub znaki nowej linii, może zmienić strukturę programu pomimo twojego cytowania.
Bezpieczny wzorzec (shell variables via env)
Poprawne zabezpieczenie: skopiuj niezaufane dane wejściowe do zmiennej środowiskowej, a następnie użyj natywnego rozwinięcia shella ($VAR) w skrypcie run. Nie osadzaj ponownie za pomocą ${{ … }} wewnątrz polecenia.
# safe
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: New issue
env:
TITLE: ${{ github.event.issue.title }}
run: |
echo "New issue $TITLE created"
Uwagi:
- Unikaj używania ${{ env.TITLE }} inside run:. To ponownie wprowadza renderowanie szablonów do polecenia i powoduje to samo ryzyko wstrzyknięcia.
- Prefer passing untrusted inputs via env: mapping and reference them with $VAR in run:.
Powierzchnie wyzwalane przez użytkowników (traktuj jako niezaufane)
Accounts with only read permission on public repositories can still trigger many events. Any field in contexts derived from these events must be considered attacker-controlled unless proven otherwise. Przykłady:
- issues, issue_comment
- discussion, discussion_comment (organizacje mogą ograniczać dyskusje)
- pull_request, pull_request_review, pull_request_review_comment
- pull_request_target (niebezpieczne przy niewłaściwym użyciu — uruchamia się w kontekście base repo)
- fork (każdy może sforkować publiczne repozytoria)
- watch (gwiazdkowanie repozytorium)
- Indirectly via workflow_run/workflow_call chains
Które konkretne pola są kontrolowane przez atakującego zależy od zdarzenia. Zapoznaj się z przewodnikiem GitHub Security Lab po niezaufanych wejściach: https://securitylab.github.com/resources/github-actions-untrusted-input/
Praktyczne wskazówki
- Minimalizuj użycie wyrażeń wewnątrz run:. Preferuj mapowanie env: i odniesienia przez $VAR.
- Jeśli musisz przekształcić dane wejściowe, rób to w shellu używając bezpiecznych narzędzi (printf %q, jq -r itp.), zaczynając nadal od zmiennej shellowej.
- Zachowaj szczególną ostrożność przy interpolowaniu branch names, PR titles, usernames, labels, discussion titles oraz PR head refs do skryptów, opcji wiersza poleceń lub ścieżek plików.
- Dla reusable workflows i composite actions stosuj ten sam wzorzec: mapuj do env, a następnie odwołuj się przez $VAR.
Referencje
- GitHub Actions: A Cloudy Day for Security - Part 1
- GitHub workflow syntax
- Contexts and expression syntax
- Untrusted input reference for GitHub Actions
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
HackTricks Cloud

