Skip to main content
BlogSecurity

Kerentanan Secrets GitHub Actions di Claude Code dan Gemini CLI

Bagaimana satu GitHub issue menjangkau secrets CI di workflow Claude Code Action, Gemini CLI dan Codex, lengkap dengan versi patch dan checklist hardening.

Matthews Wong

Software Engineer

Oktober 202611 menit baca
Kerentanan Secrets GitHub Actions di Claude Code dan Gemini CLI

Ringkasan Utama

Pada Agustus 2026 Novee Security menunjukkan bahwa sebuah GitHub issue dari akun tanpa hak apa pun di repository bisa menjangkau secrets CI lewat workflow Claude Code Action, Gemini CLI dan Codex. Patch sudah rilis: Claude Code 2.1.163, gemini-cli 0.39.1, run-gemini-cli 0.1.22. Pertahanan jangka panjangnya struktural: jauhkan teks tak tepercaya dari agent yang bisa menulis dan memegang secrets.

Bagian paling mengganggu dari sesi Black Hat USA 2026 adalah betapa sedikit yang dibutuhkan penyerang. Elad Meged dari Novee Security mempresentasikannya pada 5 Agustus, dengan premis sebuah issue yang dibuka akun tanpa privilege di repository. Tanpa fork, tanpa token curian, tanpa maintainer yang dibobol. Teks issue saja sudah cukup untuk menggiring coding agent, yang berjalan di workflow default milik vendor sendiri, menuju secrets yang ada di CI runner.

Tulisan ini adalah pembacaan catatan primer, bukan reproduksi. Saya membaca research note Cloud Security Alliance, tulisan Novee, advisory GitHub untuk Gemini CLI, entri NVD untuk CVE Claude Code, panduan keamanan Anthropic untuk action-nya dan referensi secure-use dari GitHub. Saya tidak menjalankan exploit apa pun dan tidak menuliskan payload. Semuanya tentang apa kesamaan ketiga kegagalan itu dan apa yang perlu diubah defender minggu ini.

Apa yang bisa dijangkau satu issue, dan kenapa ini masalah CI

Ketiga vendor menjalankan agent dari workflow GitHub Actions yang terpicu oleh input publik: komentar @claude, issue yang baru dibuka, issue yang dibuka atau diberi label. Menurut Novee, para peneliti menguji konfigurasi workflow default tanpa modifikasi di repository milik vendor sendiri, dan catatan CSA menyebut konfigurasi serupa kemudian ditemukan di jauh lebih dari seratus repository publik lain.

Kerangka Novee: setiap celah ada di sebuah handoff, titik ketika satu bagian harness meneruskan nilai ke bagian lain dan sebuah asumsi gagal. Siapa pun dengan akses tulis ke repository bisa membaca secrets-nya, begitu kata panduan GitHub sendiri, jadi agent yang bisa menjalankan shell di runner mewarisi kekuatan itu. Pertanyaan bagi defender bukan apakah model bisa dibujuk. Pertanyaannya: apa yang dilakukan proses pemegang secrets saat model berhasil dibujuk.

Claude Code Action: tiga ronde patch dan bypass

Novee menjelaskan tiga ronde. Di ronde satu, tool Bash disetujui lewat prefix match, dan teks dalam tanda kutip dibuang sebelum 23 validation check berjalan, sehingga payload yang disembunyikan di nilai flag tidak pernah diperiksa. Hasilnya code execution di runner dan paparan secrets workflow. Anthropic menghapus sebagian besar tool Bash dan menambah allowlist untuk git push.

Ronde dua memakai daftar command hardcoded yang dianggap read-only. Beberapa utilitas di daftar itu tidak tercakup daftar path-check terpisah, sehingga bisa membaca file di luar workspace, dan satu setting default menerbitkan output tool ke Step Summary publik tempat masking gagal menangkap string secret yang dibalik. Anthropic mematikan setting itu dan membersihkan output. Panduan keamanannya hari ini masih memperingatkan bahwa show_full_output bisa membocorkan credentials dan log di repository publik terbuka untuk umum.

Ronde tiga yang mendapat CVE. Entri NVD untuk CVE-2026-54316 menyebut bahwa dari versi 0.2.54 sampai 2.1.163, hostname huggingface.co dipra-setujui polos untuk tool WebFetch, sehingga path apa pun di sana, termasuk repository model milik penyerang, diambil tanpa prompt dan tanpa batasan allowedTools. Hugging Face menghitung fetch itu sebagai download, dan itu menjadi kanal tersembunyi: Novee menjelaskan hingga 64 repository yang menyandikan karakter secret di download counter-nya. Perbaikannya di 2.1.163, dan teks NVD sendiri mencatat bahwa eksploitasi yang andal butuh konten tak tepercaya masuk ke context window.

Gemini CLI: trust dan parent process yang bisa dibaca

Advisory GHSA-wpqr-6v78-jr5g, yang membawa CVE-2026-12537 dan skor CVSS 10.0, menyebut dua cacat di mode headless. Run headless otomatis mempercayai workspace saat memuat konfigurasi dan environment variable, sehingga setting berbahaya di direktori .gemini lokal bisa berujung code execution pada konten tak tepercaya. Lalu di bawah --yolo, tool allowlist granular di settings.json diabaikan, sehingga run_shell_command yang masuk allowlist bisa dikendalikan lewat prompt injection.

Rantai Novee dimulai dari workflow dedup issue yang berjalan untuk pengguna GitHub mana pun yang membuka issue, dalam mode yolo, dengan konfigurasi yang dimaksudkan hanya mengizinkan echo dan gh issue view. Pengecekan prefix match justru mendaftarkan tool shell penuh. Asumsi kedua adalah isolasi secret: environment child process dibersihkan, tetapi parent memegang secrets dan berbagi UID serta PID namespace dengan child, sehingga environment parent tetap terbaca. Novee melaporkan 114 repository menjalankan pola yang sama.

Versi yang sudah diperbaiki adalah gemini-cli 0.39.1 (dan 0.40.0-preview.3) serta run-gemini-cli 0.1.22. Advisory memperingatkan sebagian workflow bisa rusak atau gagal diam-diam setelah update, karena folder trust sekarang eksplisit di mode headless. Workaround terdokumentasi untuk input tepercaya adalah environment variable GEMINI_TRUST_WORKSPACE bernilai true. Untuk input tak tepercaya, ikuti dulu panduan hardening di repository run-gemini-cli.

Codex: tanpa CVE, dan sandbox bekerja sesuai dokumentasi

Kasus OpenAI paling halus karena tidak ada yang rusak. Issue deduplicator openai/codex menjalankan dua pass Codex dalam satu job dengan checkout bersama, pada issue yang dibuka atau diberi label, dengan allow-users diisi wildcard. Menurut Novee, sandbox workspace-write default melindungi .git, .codex dan .agents tetapi tidak AGENTS.md, file instruksi default Codex, sehingga pass satu bisa menulis file yang dimuat pass dua sebagai instruksi otoritatif.

Validasi yang gagal di antara kedua pass memicu pass kedua, artinya kegagalan validasi itu sendiri yang mengantarkan instruksi beracun. OpenAI menganggap sandbox berperilaku sesuai dokumentasi, jadi tidak ada CVE dan tidak ada versi untuk di-upgrade. Menurut Novee, repository mereka diperbaiki sekitar tiga hari setelah laporan: job terpisah, tanpa checkout, sandbox read-only untuk step Codex, dan AGENTS.md didokumentasikan sebagai input tak tepercaya.

Ketiga agent dibandingkan

Tabel ini menaruh tiga kegagalan dalam satu kerangka. Kolom yang paling layak dipelajari adalah kolom ketiga. Tidak ada satu pun yang berupa model menolak dengan buruk. Masing-masing adalah kode harness deterministik yang memercayai nilai yang tidak punya alasan untuk dipercaya.

AgentTrigger publikAsumsi yang gagalIdentifier dan perbaikan
Claude Code ActionKomentar @claude di tag mode, yang menjadi defaultTeks dalam kutip aman dilewati; hostname di allowlist berarti semua path amanCVE-2026-54316, diperbaiki di Claude Code 2.1.163
Gemini CLI dan run-gemini-cliPengguna mana pun yang membuka issue, agent dalam mode yoloAllowlist ditegakkan; parent process di luar jangkauan childCVE-2026-12537, diperbaiki di gemini-cli 0.39.1 dan run-gemini-cli 0.1.22
OpenAI CodexIssue dibuka atau diberi label, semua author diizinkanFile yang ditulis pass pertama bukan input bagi pass keduaTanpa CVE; hardening workflow di openai/codex

Catatan soal skor. Anthropic menilai CVE-2026-54316 di CVSS v4 6.0, Moderate, sementara catatan NVD memuat skor CVSS v3.1 9.1, Critical, dari nvd@nist.gov. Kedua angka menggambarkan celah yang sama dengan metode dan pandangan berbeda tentang seberapa sulit memasukkan konten tak tepercaya ke context. Gunakan severity untuk mengurutkan antrean patch Anda berdasarkan apa yang bisa dijangkau workflow, bukan skor mana yang Anda lihat lebih dulu.

Trade-off: agent yang sudah di-patch di workflow yang tidak berubah

Kegagalan pertama adalah yang ditandai tulisan Novee untuk Codex: perbaikan tidak sampai ke salinan workflow di hilir. Vendor bisa mengeraskan repository-nya dalam tiga hari, tetapi salinan YAML itu di repository Anda tetap persis seperti semula. Upgrade action menutup CVE spesifiknya dan membiarkan bentuk workflow, trigger publik yang mengumpan agent yang bisa menulis, tetap utuh.

Kedua adalah biaya perbaikannya. Google merilis breaking change pada model trust untuk run headless, bukan patch sempit, dan advisory memperingatkan kegagalan diam-diam. Jika Anda menaikkan versi lalu workflow tidak melakukan apa-apa, godaannya adalah mengisi GEMINI_TRUST_WORKSPACE true di semua tempat agar hijau lagi. Itu memulihkan paparan awal. Isi hanya di tempat setiap input berasal dari kolaborator tepercaya.

Ketiga adalah mitigasi yang lemah. Panduan Anthropic menyebut bahwa dengan allowed_non_write_users, pembersihan secrets dari environment subprocess bersifat best effort dan mengurangi, bukan menghilangkan, risiko, dan tool allowlist pun mungkin tidak menghilangkan risiko pemulihan token. Kontrol di dalam agent adalah lapisan kedua. Lapisan pertama harus berada di luarnya.

Menurut catatan CSA, Google menghapus tiga workflow ADK (issue-analyze.yml, issue-fix.yml, pr-analyze.yml) dalam hitungan hari setelah disclosure. Jika tim yang menulis sebuah agent memilih menghapus workflow daripada mem-patch-nya, menghapus workflow Anda juga pilihan yang sah.

Workflow yang selamat dari issue yang sama

Struktur di bawah ini adalah sintesis saya dari panduan keamanan Anthropic dan referensi secure-use GitHub, bukan template vendor. Isinya empat hal: token default read-only, trigger yang dibatasi berdasarkan siapa yang berkomentar, nilai tak tepercaya diteruskan ke shell lewat environment variable alih-alih interpolasi expression, dan tool allowlist yang cukup sempit sampai membosankan.

# .github/workflows/claude-triage.yml
name: claude-triage
on:
  issue_comment:
    types: [created]

# Read-only default. Grant more per job only when a step proves it needs it.
permissions:
  contents: read

jobs:
  triage:
    # The action also checks that the commenter has write access. This gate
    # means a stranger's comment never starts a job that holds the model key.
    if: >-
      contains(github.event.comment.body, '@claude') &&
      contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
               github.event.comment.author_association)
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write          # comment and label only. No contents: write.
    steps:
      # Wrong: expression interpolation pastes issue text into the script.
      #   run: echo "Title is ${{ github.event.issue.title }}"
      # Right: hand it over as data through an environment variable.
      - name: Log the title safely
        env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: printf 'Triaging: %s\n' "$ISSUE_TITLE"

      # Pin to a full-length SHA from the action's own repository, not a tag.
      - uses: anthropics/claude-code-action@<full-length-commit-sha>
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          # The job-scoped token expires with the job. Never a personal token.
          github_token: ${{ secrets.GITHUB_TOKEN }}
          # Narrow enough to be boring: read the issue, nothing else.
          claude_args: '--allowedTools "Bash(gh issue view:*)"'

# Do not add allowed_non_write_users or allowed_bots unless the job's
# permissions are limited to something like issues: write.

Pin action ke commit SHA panjang penuh yang diambil dari repository action itu sendiri, karena GitHub mencatat tag bisa dipindah atau dihapus jika repository-nya dibobol. Teruskan GITHUB_TOKEN berumur pendek, bukan personal access token, karena Anthropic menyebut token statis tidak dirotasi dan bisa dipulihkan seiring waktu lewat prompt injection.

Pecah pipeline menjadi dua job. Job pertama membaca issue tanpa secrets dan tanpa izin tulis, lalu mengeluarkan ringkasan teks biasa sebagai artifact. Job kedua, yang memegang model key, hanya memakai ringkasan itu di checkout bersih. Ini pemisahan yang sama yang diterapkan OpenAI pada Codex, dan sekaligus menjawab masalah workspace bersama.

Yang dikerjakan hari Senin

Kerjakan berurutan. Dua langkah pertama memakan satu jam dan menutup sebagian besar paparan.

  1. Inventarisasi semua workflow yang menjalankan coding agent dan catat trigger-nya. Apa pun yang terpicu issues, issue_comment, pull_request_target atau workflow_run di repository publik masuk cakupan. Perintah audit di bawah menemukan flag berisiko.
  2. Upgrade: Claude Code ke 2.1.163 atau lebih baru, gemini-cli ke 0.39.1 atau lebih baru, run-gemini-cli ke 0.1.22 atau lebih baru. Jika workflow mem-pin gemini_cli_version, advisory meminta naik ke versi yang sudah di-patch dan mengaudit setting workflow.
  3. Rotasi. Catatan CSA merekomendasikan merotasi secrets, scope GITHUB_TOKEN dan model API key yang terjangkau dari workflow mana pun yang berjalan di konfigurasi rentan sebelum patch. Anggap key apa pun yang ada dalam cakupan mungkin sudah terbaca.
  4. Kecilkan blast radius: contents read sebagai permission default, tanpa personal access token, bot dan non-write user dimatikan, mode yolo atau auto-approve dimatikan untuk apa pun yang bisa dijangkau input berprivilege rendah, dan outbound allowlist ditinjau seperti aturan firewall.
  5. Tambahkan deteksi. CSA menyarankan memantau akses mencurigakan seperti proses yang membaca /proc/*/environ, dan log workflow di repository publik layak dicek untuk apa pun yang seharusnya tidak pernah tercetak.
# 1. Which workflows can a stranger trigger, and which flags widen trust?
grep -rEn "issues:|issue_comment|pull_request_target|workflow_run" .github/workflows
grep -rEn "allowed_non_write_users|allowed_bots|yolo|allow-users|GEMINI_TRUST_WORKSPACE" \
  .github/workflows

# 2. Which agent versions are pinned? Compare against the fixed releases:
#    Claude Code 2.1.163, gemini-cli 0.39.1, run-gemini-cli 0.1.22.
grep -rEn "gemini_cli_version|claude-code-action@|run-gemini-cli@" .github/workflows

# 3. Are any actions pinned to a movable tag instead of a 40-character SHA?
grep -rEn "uses: .*@(v[0-9]|main|master)" .github/workflows

# 4. Set the repository default token to read-only (organisation admins can
#    do the same at org level). Needs a token with repo administration rights.
gh api -X PUT repos/OWNER/REPO/actions/permissions/workflow \
  -f default_workflow_permissions=read

Jika agent memang perlu menjawab orang asing, misalnya triase issue publik, beri GITHUB_TOKEN yang hanya bisa memberi label dan berkomentar, tanpa secret selain model key miliknya, dan repository atau environment terpisah sehingga kebocoran hanya merugikan key itu dan tidak lebih.

Aturan yang saya ambil: agent yang membaca teks publik dan agent yang memegang secrets tidak boleh menjadi proses yang sama. Ketiga bug itu adalah tiga cara berbeda membuat keduanya menjadi proses yang sama. Patch versinya hari ini, lalu desain ulang workflow agar bug handoff berikutnya tidak punya apa-apa untuk dicuri.

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apakah GitHub issue benar-benar bisa membocorkan secrets CI lewat AI coding agent?

Menurut disclosure Novee Security Agustus 2026, ya: issue dari akun tanpa privilege di repository menjangkau secrets CI runner di repository milik vendor sendiri. Agent berjalan di workflow default yang terpicu input publik. Kelemahannya ada pada cara harness memercayai nilai, bukan hanya pada model.

Versi mana yang memperbaiki celah Claude Code dan Gemini CLI?

Claude Code 2.1.163 memperbaiki CVE-2026-54316 yang memengaruhi 0.2.54 sampai sebelum rilis itu. Untuk Gemini CLI, GHSA-wpqr-6v78-jr5g diperbaiki di gemini-cli 0.39.1 (dan 0.40.0-preview.3) serta run-gemini-cli 0.1.22. Codex tidak punya CVE maupun perbaikan versi.

Kenapa CVE-2026-54316 punya dua skor severity berbeda?

Anthropic menilainya CVSS v4 6.0, Moderate, sedangkan NVD mencantumkan CVSS v3.1 9.1, Critical. Catatan CSA mengaitkan selisih itu dengan metodologi skor dan perbedaan pandangan tentang sulitnya memasukkan konten tak tepercaya ke context Claude Code. Urutkan patch berdasarkan apa yang bisa dijangkau workflow Anda.

Apakah upgrade agent saja sudah cukup aman?

Tidak. Upgrade menutup CVE spesifiknya, tetapi tidak pola trigger publik yang mengumpan agent berhak tulis pemegang secrets. Perbaikan vendor juga tidak sampai ke salinan workflow di hilir. Kurangi juga permission GITHUB_TOKEN, pisahkan input tak tepercaya dari job berprivilege dan rotasi secrets.

Apa yang harus saya ubah di workflow GitHub Actions minggu ini?

Inventarisasi workflow yang menjalankan coding agent pada issue, komentar atau pull_request_target, lalu upgrade agent dan rotasi secrets yang terjangkau. Set token default ke contents read, hindari personal access token, dan matikan mode yolo atau auto-approve untuk input berprivilege rendah. Pin action ke commit SHA penuh.