FlawOpen

flawopen.com/Keamanan GitHub Actions/Injeksi skrip workflow

Bagaimana injeksi skrip GitHub Actions terjadi dan cara mencegahnya?

Dampak tinggi jika berhak istimewa CWE-78 Keamanan workflow CI/CD
Penjelasan sederhana

Workflow dapat mengubah data menjadi sintaks shell jika judul issue atau kolom pull request disisipkan ke skrip sebelum Bash berjalan. Ibarat pencetak tanda nama yang mengira nama sebagai instruksi. Kirim nilai lewat variabel lingkungan dan kutip ekspansinya saat dipakai sebagai data; Bash menerimanya terpisah dari skrip. Dampak bergantung pada token, secret, runner, dan pemicu.

Konteks tak tepercayaKolom peristiwa GitHub seperti judul, isi, nama branch, label, dan pesan commit. Anggap sebagai teks yang dikendalikan pihak luar.
Substitusi ekspresiGitHub mengevaluasi ${{ ... }} sebelum shell dimulai. Dalam run:, masukan dapat masuk ke sumber skrip.
Serah-terima lingkunganPemetaan ke env: mengirim nilai sebagai data proses. Kutip ekspansi shell, hindari eval dan skrip dinamis.
Batas hak aksesPeristiwa dan workflow menentukan izin token, secret, dan akses runner. Dampak terbatas pada sumber daya yang dapat dijangkau job.

Akar masalah: data disisipkan sebelum shell mengurai skrip

GitHub memperluas ekspresi sebelum menjalankan shell untuk langkah run. Judul tak tepercaya yang disisipkan langsung dapat mengubah program shell. Nilai melalui env: terpisah dari teks skrip; jika dikutip, ia tetap menjadi argumen untuk perintah biasa. Penggunaan berikutnya dengan eval, interpreter lain, atau alat yang menafsirkan argumen sebagai kode tetap berbahaya. GitHub menganggap kolom peristiwa sebagai masukan yang mungkin dikendalikan penyerang.

.github/workflows/triage.yml (Interpolasi tidak aman)Tidak aman
# TIDAK AMAN: data peristiwa menjadi bagian skrip shell yang dibuat
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        run: |
          printf 'Title: %s\n' "${{ github.event.issue.title }}"
.github/workflows/triage.yml (Data dipisah)Diperkeras
# Lebih aman: kirim nilai peristiwa melalui lingkungan
name: Issue Triage
on:
  issues:
    types: [opened]

permissions:
  contents: read

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - name: Print issue title
        env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: |
          printf 'Title: %s\n' "$ISSUE_TITLE"

Ringkasan jalur serangan

Step 1

Pengguna mengendalikan kolom peristiwa

Contohnya judul issue publik, judul pull request, atau nama branch menjadi masukan workflow.

Step 2

Workflow menyisipkannya ke sumber shell

Ekspresi langsung ${{ github.event... }} di run: dievaluasi sebelum Bash mengurai skrip.

Step 3

Shell menafsirkan program yang berubah

Jika nilai mengubah sintaks shell, perintah berjalan sebagai proses job. Jika tetap data dalam argumen berkutip, injeksi ini tidak terjadi.

Step 4

Izin job menentukan dampak

Job yang disusupi hanya menjangkau sumber daya yang tersedia pada run itu: izin GITHUB_TOKEN, secret yang diberikan, dan runner. Tinjau pemicu issue serta pull_request_target.

Daftar periksa penguatan

Sumber primer

Jelajahi topik keamanan dan analisis terkait:Direktori keamanan lengkap →
Lihat juga Cosign GHSA-fx35-mq7g-6g98: bypass verifikasi bundle Dependency Confusion: risiko dan pertahanan Paparan Socket Docker: Risiko dan Perlindungan