FlawOpen

flawopen.com/Teardowns/cve-2026-84973-jupyterlab-snapshot-checkout-toctou

● CVE-2026-84973 · Tinggi
Riset Keamanan · FlawOpen

CVE-2026-84973: Kerentanan TOCTOU pada alur snapshot JupyterLab

Pemeriksaan waktu berpresisi satu detik dapat membuat alur snapshot melakukan checkout dan menjalankan commit pull request yang belum disetujui dengan hak akses job. Perbarui update-snapshots-checkout ke versi 1.0.0 atau lebih baru.

💡 Penjelasan Sederhana (ELI5)

Peninjau menyetujui paket tertentu, tetapi loket hanya memeriksa angka detik pada jam. Jika paket diganti pada detik yang sama, paket pengganti tampak ikut disetujui. Action ini membandingkan waktu dengan presisi satu detik dan menerima nilai yang sama, sehingga pembaruan pull request dapat lolos bersamaan dengan komentar maintainer.

Konsep Kunci & Istilah

TOCTOU
Time-of-check to time-of-use: keputusan keamanan dibuat untuk sumber daya yang berubah sebelum digunakan.
SHA head pull request
Pengenal commit yang tidak berubah di ujung cabang pull request. Alur kerja seharusnya hanya menjalankan commit persis yang disetujui.
Izin token GitHub Actions
Operasi repositori yang boleh dilakukan GITHUB_TOKEN milik job, seperti membaca atau menulis konten dan pull request.
CWE-367 / CWE-829
Advisory mengklasifikasikan kondisi balapan waktu sebagai CWE-367 dan eksekusi fungsi yang dikendalikan pull request sebagai CWE-829.

Pemetaan kerangka kerja

  • Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-367 CWE-829

Analisis Akar Masalah (Root Cause)

Sebelum versi 1.0.0, update-snapshots-checkout mengambil pushed_at dari pull request dan created_at dari komentar pemicu, mengubah keduanya menjadi detik Unix, lalu menolak proses hanya jika pushed_at lebih besar secara ketat. Kedua timestamp API berpresisi satu detik. Push dan komentar yang disetujui pada detik yang sama dapat bernilai sama dan lolos. Action lalu menyimpan SHA head saat ini dan memeriksanya setelah checkout; pemeriksaan itu hanya membuktikan checkout cocok dengan SHA yang baru diambil, bukan bahwa maintainer menyetujui commit tersebut. Perbaikan upstream mengganti -gt dengan -ge untuk menolak nilai sama maupun push yang lebih baru. Risiko hanya berlaku pada alur kerja yang memakai versi rentan lalu menjalankan konten pull request; dampaknya dibatasi oleh izin dan kredensial alur kerja.

Alur Serangan Langkah demi Langkah

Langkah 1

Maintainer tepercaya memicu alur kerja

Pull request dibuka, lalu OWNER, COLLABORATOR, atau MEMBER mengirim komentar yang memicu alur pembaruan snapshot.

Langkah 2

Pembaruan yang dikendalikan penyerang terjadi pada detik yang sama

Kontributor memperbarui cabang pull request pada detik yang sama. Presisi API satu detik memungkinkan nilai waktu Unix menjadi sama.

Langkah 3

Perbandingan lebih-besar-ketat menerima nilai sama

Action rentan hanya menolak jika pushed_at lebih besar daripada created_at. Nilai sama tidak memenuhi kondisi itu sehingga SHA head baru dicatat.

Langkah 4

Alur kerja melakukan checkout dan dapat menjalankan commit tersebut

Checkout cocok dengan SHA yang dicatat dan lolos pemeriksaan berikutnya. Jika langkah selanjutnya menjalankan action atau skrip dari pull request, izin dan kredensial job akan digunakan.

Langkah 5

Perbarui dan kurangi kewenangan alur kerja

Perbarui ke 1.0.0 atau lebih baru. Pin action ke SHA yang tidak berubah, berikan GITHUB_TOKEN izin minimum, dan jauhkan kode pull request yang tidak tepercaya dari rahasia serta job istimewa.

Kode Sumber: Rentan vs Aman

Ini sesuai perbaikan satu baris upstream: -ge menolak nilai yang sama pada presisi waktu API. Perubahan ini menutup bypass pada detik yang sama. Tetap ikat persetujuan pada SHA yang tidak berubah dan minimalkan izin; urutan waktu bukan pengganti keputusan otorisasi yang tetap. Diff upstream mempertahankan pesan diagnostik yang ada; pesannya menyebut “setelah”, meskipun nilai yang sama kini juga ditolak.

IMPLEMENTASI RENTAN
if [[ $(date -d "$pushed_at" +%s) -gt $(date -d "$COMMENT_AT" +%s) ]]; then
    echo "Updating is not allowed because the PR was pushed to (at $pushed_at) after the triggering comment was issued (at $COMMENT_AT)"
    exit 1
fi
PERBAIKAN AMAN & KUAT
if [[ $(date -d "$pushed_at" +%s) -ge $(date -d "$COMMENT_AT" +%s) ]]; then
    echo "Updating is not allowed because the PR was pushed to (at $pushed_at) after the triggering comment was issued (at $COMMENT_AT)"
    exit 1
fi

Daftar Periksa Penguatan Sistem Rekayasa

Sumber