--di Git bukan terminator opsi umum, melainkan pemisah antara revisi dan spesifikasi path, sehingga untuk meneruskan revisi yang tidak tepercaya dengan aman diperlukan--end-of-options, yang didukung sejak Git 2.24.0- Dalam
git log --end-of-options "$rev" -- "$path", penanda pertama memisahkan opsi dan revisi, sedangkan--di belakang memisahkan revisi dan path; keduanya tidak dapat saling menggantikan - Meski menjalankan array
argvlangsung tanpa shell, jika input yang diawali tanda hubung ditafsirkan sebagai opsi seperti--upload-pack,core.sshCommand, atauProxyCommand, injeksi argumen CWE-88 dapat terjadi - Dari 19 package manager yang diteliti, 17 menjalankan binary Git sebagai cara default atau satu-satunya, tetapi alat yang memakai
--end-of-optionshanyalahcmd/gomilik Go - Penanganan mendasar memiliki biaya kompatibilitas karena harus menaikkan versi minimum Git menjadi 2.24.0, 2.30.0, atau 2.43.1 tergantung subcommand; sementara library Git menghilangkan batas injeksi argumen, tetapi harus melacak sendiri perbaikan keamanan checkout dari upstream
Perbedaan antara -- dan --end-of-options
- Pada tool Unix umum,
--menandai akhir pemrosesan opsi, sehinggarm -- -fmemperlakukan-fsebagai nama file, bukan opsi hapus paksa - Sejak awal, Git menggunakan
--sebagai pemisah antara revisi dan spesifikasi path (pathspec)git log fooambigu: apakah yang dimaksud branch bernamafooatau file bernamafoogit log main -- README.mdberarti commit dimainyang menyentuhREADME.md
- Karena desain ini, tidak ada penanda akhir opsi pada posisi revisi, dan dalam
git log "$rev", jika$revdiawali tanda hubung, Git menafsirkannya sebagai opsi - Commit yang memperkenalkan
--end-of-optionsmenjelaskan bahwa karena--yang sudah ada dipakai untuk memisahkan revisi dan spesifikasi path, diperlukan penanda terpisah untuk membedakan opsi dan revisi --end-of-optionsdidokumentasikan di gitcli(7), dan ditambahkan pada November 2019 saat Git 2.24.0 dirilis
Cara penggunaan yang benar per perintah
git clone -- "$url"mengikuti konvensi POSIX padaclone, sehingga--sebelum URL mengakhiri pemrosesan opsi--di belakang padagit checkout "$ref" --menandai$refsebagai revisi, bukan nama file, tetapi tidak mencegah$refditafsirkan lebih dulu sebagai opsi- Untuk meneruskan revisi dan path yang tidak tepercaya secara aman sekaligus, gunakan kedua penanda seperti
git log --end-of-options "$rev" -- "$path"--end-of-optionsmemisahkan opsi dan revisi--memisahkan revisi dan path
- Jika kedua penanda dianggap bisa saling dipertukarkan, input yang diawali tanda hubung tidak akan terblokir
Waktu dukungan berbeda untuk tiap subcommand
- Dukungan
--end-of-optionstidak diterapkan sekaligus ke semua perintah Git, tetapi ditambahkan per subcommand git rev-parsemenggunakan parser argumennya sendiri, sehingga mulai mendukungnya di Git 2.30.0, satu tahun setelah pengenalan awalgit checkoutdangit resetmenafsirkan--sendiri, dan implementasi awal meninggalkan--end-of-optionsdi daftar argumen sehingga keduanya menolaknya- Masalah ini diselesaikan pada Februari 2024 saat Git 2.43.1 dirilis
Injeksi argumen juga terjadi tanpa shell
- Git, Mercurial, dan SSH memiliki opsi resmi untuk menjalankan perintah yang ditentukan pemanggil
git clone --upload-pack=<cmd>menentukan binary sisi server-c core.sshCommand=<cmd>pada semua pemanggilan Git mengubah perintah koneksi--config=alias.<subcmd>=!<shell>di Mercurial mendefinisikan ulang subcommand yang akan dijalankan sebagai skrip shell arbitrer-oProxyCommand=<cmd>di SSH menentukan perintah proxy
- Jika program wrapper memasukkan string yang tidak tepercaya ke daftar argumen, fitur-fitur ini dapat berubah menjadi sarana serangan
- Jenis kegagalan ini termasuk CWE-88 injeksi argumen (argument injection) dan berbeda dari injeksi perintah shell
- Ini tetap terjadi meski program menggunakan array
argvdanexec, bukansystem() - Array diteruskan ke Git tanpa rusak, tetapi Git menafsirkan argumen yang diawali tanda hubung sebagai opsi
- Ini tetap terjadi meski program menggunakan array
docker buildCVE-2019-13139 adalah contoh yang memakaios/execdan arrayargvmilik Go tanpa melalui shell- Fragmen
#ref:dirpada URL konteks Git diteruskan kegit fetch origin <ref>, lalu<ref>ditafsirkan sebagai--upload-pack=<cmd>
- Fragmen
Kerentanan yang berulang di berbagai sistem version control
- Pada hari yang sama pada Agustus 2017, pola yang sama diungkap di empat sistem version control
- CVE-2017-1000117 di Git
- CVE-2017-1000116 di Mercurial
- CVE-2017-9800 di Subversion
- CVE-2017-12836 di CVS
- Keempat sistem meneruskan hostname dari URL sebagai argumen SSH, dan hostname yang diawali
-oProxyCommand=diproses sebagai opsi SSH - Menurut postmortem Phabricator, dari tiga tool yang saat itu masih aktif dipelihara, hanya Subversion yang menambahkan
--sebelum hostname- Git dan Mercurial memvalidasi format hostname, antara lain karena tidak semua implementasi SSH mendukung
--
- Git dan Mercurial memvalidasi format hostname, antara lain karena tidak semua implementasi SSH mendukung
- Kode yang tidak memiliki
--juga tampak dan bekerja normal sampai argumennya diawali tanda hubung, sehingga mekanisme ini pada dasarnya tidak aman
Jalur paparan package manager
- Package manager menerima URL Git atau ref dari manifest, lock file, dan metadata dependensi transitif, lalu meneruskannya ke subprocess
gem 'foo', git: '...'di Gemfilegithub:user/repo#refdipackage.json- Konfigurasi setara di
pyproject.toml,Cargo.toml,mix.exs,Package.swift,pubspec.yaml,conanfile.py, dango.mod
- Per HEAD Juli 2026, 17 dari 19 package manager yang diteliti menjalankan binary Git sebagai jalur default atau satu-satunya
- Dua sisanya memakai library secara default
- Cargo memakai libgit2 dan menjalankan proses Git jika
net.git-fetch-with-clidiaktifkan - Poetry beralih ke dulwich sejak 1.2.0 dan dapat memakai Git sistem melalui pengaturan
system-git-client
- Cargo memakai libgit2 dan menjalankan proses Git jika
- Nix memakai libgit2 saat membaca repository lokal, tetapi menjalankan proses Git untuk fetch karena libgit2 tidak mendukung helper git-credential
- Target penelitian adalah Bundler, Cargo, CocoaPods, Composer, Conan, Go, Helm, Homebrew, Mix, Nix, npm, pip, pnpm, Poetry, Pub, SwiftPM, uv, vcpkg, dan Yarn
CVE yang dikonfirmasi pada package manager
- Kerentanan package manager yang dipublikasikan untuk jenis ini mencakup kasus berikut
- CVE-2021-43809 di Bundler
- CVE-2021-29472, CVE-2022-24828 di Composer
- CVE-2022-36069 di Poetry
- CVE-2023-5752 di pip
- CVE-2022-21223, CVE-2022-24440 di CocoaPods
- CVE-2025-68119 di Go
- Snyk, yang menemukan beberapa kerentanan tahun 2022, memublikasikan riset injeksi argumen di Git dan Mercurial
- Sonar mengelola daftar opsi berbahaya per binary
Kondisi pertahanan nyata dan perbaikan Go
- Dari 17 package manager yang menjalankan proses Git, tool yang menggunakan
--end-of-optionshanyalahcmd/gomilik Go - Pada Juni 2019, Go menambahkan
--sebelum URL repository sebagai penguatan pertahanan umum - Pada Januari 2026, terungkap bahwa
--saja tidak cukup, sehingga sebagai perbaikan CVE-2025-68119, Go menambahkan--end-of-optionssecara luas - Perbaikan yang sama juga mencakup
HGPLAIN=+strictflags- Pengaturan ini membatasi pemrosesan opsi awal Mercurial sejak 2017, saat Mercurial 4.4.2 dirilis
- Commit perbaikan Go menyebut bahwa perubahan yang lebih struktural mungkin diperlukan agar masalah yang sama sulit muncul kembali, tetapi untuk saat ini perbaikan tersebut menyelesaikan masalah yang ada
Sebagian besar pertahanan ditambahkan setelah kerentanan dipublikasikan
- Package manager lain, meski melindungi daftar argumen, umumnya memakai
--atau menolak tanda hubung di awal input --sebelum URLgit clonedi Bundler ditambahkan lewat patch CVE-2021-43809- Penolakan tanda hubung di awal pada cocoapods-downloader diterapkan dalam tiga commit selama sepuluh hari pada Maret 2022, bertepatan dengan waktu publikasi CVE-2022-21223
- Pertahanan Poetry ditambahkan pada September 2021, CVE diberikan satu tahun kemudian, dan enam bulan setelah itu Poetry beralih ke dulwich
- vcpkg adalah pengecualian: sejak hari pertama dukungan registry Git ditulis, vcpkg sudah memakai
--
Batasan kompatibilitas dari versi minimum Git
- Advisory CVE-2022-24828 Composer menyebut
--end-of-optionssebagai perbaikan yang benar, tetapi karena harus mendukung Git yang lebih lama, Composer memilih menolak nama branch yang diawali tanda hubung - Integrasi Git vcpkg menetapkan versi minimum Git 2.7.4, sedangkan
HOMEBREW_MINIMUM_GIT_VERSIONuntuk Linux di Homebrew adalah 2.7.0 yang ditetapkan pada 2018 - Dengan berakhirnya masa pakai Amazon Linux 2, yang menyediakan Git 2.14.3, pada Juni 2026, distribusi yang diikuti oleh batas bawah seperti ini baru sekarang keluar dari cakupan dukungan
- Status dukungan jangka panjang Ubuntu juga mempersulit migrasi serentak
- Ubuntu 18.04 menyediakan Git 2.17.0 dan mendapat extended support hingga 2028
- Ubuntu 20.04 menyediakan Git 2.25.1 dan mendapat extended support hingga 2030
- Git 2.25.1 menerima
--end-of-optionspadagit fetch, tetapi menolaknya padagit rev-parse
- Untuk bergantung pada
--end-of-options, sebagian besar subcommand harus mensyaratkan versi minimum Git 2.24.0,rev-parse2.30.0, sertacheckoutdanreset2.43.1 - Menaikkan versi minimum membuat pengguna yang memakai Git lama bawaan distribusi tidak lagi dapat didukung
Menggunakan library Git alih-alih menjalankan proses
- libgit2, gitoxide, go-git, JGit, dan dulwich mengimplementasikan protokol transport Git yang diperlukan untuk clone dan fetch di dalam proses
- Karena tidak ada batas
argvterpisah, tidak ada target yang bisa diinjeksi ke daftar argumen - Jujutsu memakai gitoxide untuk integrasi Git dan tidak memiliki CVE publik bertipe injeksi argumen
- Dua advisory hingga saat ini adalah path traversal dan ketiadaan pemeriksaan tabrakan SHA-1 yang diwarisi dari library
- CVE-2025-21613 pada go-git terbatas pada transport
file://- Jalur ini adalah satu-satunya jalur kode di go-git yang menjalankan binary Git
- Jika menyertakan implementasi Git sendiri, semua perbaikan keamanan checkout yang dirilis upstream Git harus dilacak, dan baik libgit2 maupun JGit pernah beberapa kali membutuhkan perbaikan terkait hal ini
- Biaya ini memang nyata, tetapi masalahnya berubah menjadi menerapkan alur patch upstream yang konkret, alih-alih harus terus mengingat validasi argumen secara permanen di setiap titik pemanggilan
Cakupan perubahan yang diusulkan untuk Homebrew
- PR Homebrew menaikkan versi minimum Git menjadi 2.30.0 dan menambahkan
--end-of-optionsdi lokasi berikut- Sebelum URL pada
clone,remote set-url, danls-remote - Sebelum ref pada
rev-parse
- Sebelum URL pada
- Pemanggilan
checkoutdanresettidak diubah- Untuk melindungi kedua perintah tersebut, diperlukan Git 2.43.1 yang dirilis pada Februari 2024
- Versi ini lebih baru daripada Git yang disediakan banyak distribusi yang saat ini masih didukung
1 komentar
Komentar di Lobste.rs
Terutama, pengetahuan yang dipelajari dari satu perintah
jjsecara alami berlaku juga pada perintah lain. Dokumentasigit logmengalami ledakan flag untuk tiap opsi keluaran, bercampur dengan “notasi khusus” untuk sintaks rentang commit serta flag filter tambahan, dan hanya sedikit pengetahuan yang bisa ditransfer ke perintah Git lainSebaliknya, dokumentasi
jj logbegitu ringkas hingga masih menyisakan ruang kosong dalam satu halaman. Kompleksitas Git yang serba campur aduk digantikan oleh tiga hal: himpunan revisi, himpunan file, dan DSL templat keluaran; semuanya digunakan secara konsisten di seluruh jj, sehingga jauh lebih sederhana, dapat dikomposisikan, dan intuitif. Memang perlu diingat bahwa Git telah menumpuk banyak embel-embel selama 20 tahun, tetapi jj tampaknya jauh lebih berpeluang menghindarinya--sebelum argumen yang diberikan pengguna, tetapi jika sampai menuntut aturan transformasi tersendiri seperti ini, itu menjadi jebakan yang terlalu berbahaya--dipilih untuk menghilangkan ambiguitas argumen file. Alih-alih cara sederhana yang menerima file sebagai argumen eksplisit, apakah ada kompromi desain yang tidak tampak dari luar sehingga pilihan ini diambil?Jika melihat kembali perdebatan Tcl dan Scheme pada 1990-an, mungkin dalam kasus ini “yang lebih buruk itu lebih baik” memang benar. Sementara keluarga S-expression, termasuk JSON dan XML, hampir tidak mengakar di ekosistem UNIX, Tcl memiliki pendekatan yang relatif berprinsip untuk melapiskan subbahasa di dalam string