- Git’teki
--, genel amaçlı bir seçenek sonlandırıcı değil, revizyonlarla yol belirtimlerini ayırdığı için, güvenilmeyen bir revizyonu güvenli biçimde geçirmek adına Git 2.24.0’dan beri desteklenen--end-of-optionsgerekir git log --end-of-options "$rev" -- "$path"içinde baştaki işaret seçeneklerle revizyonları, sondaki--ise revizyonlarla yolları ayırır; birbirlerinin yerine kullanılamazlar- Shell kullanmadan
argvdizisini doğrudan çalıştırsanız bile, tireyle başlayan girdi--upload-pack,core.sshCommand,ProxyCommandgibi seçenekler olarak yorumlanırsa CWE-88 argüman enjeksiyonu oluşabilir - İncelenen 19 paket yöneticisinin 17’si varsayılan ya da tek yöntem olarak Git ikilisini çalıştırıyor; ancak
--end-of-optionskullanan araç yalnızca Go’nuncmd/goaracıydı - Temel çözüm, alt komuta göre asgari Git sürümünü 2.24.0·2.30.0·2.43.1’e yükseltmeyi gerektiren bir uyumluluk maliyeti getirir; Git kütüphaneleri ise argüman enjeksiyonu sınırını ortadan kaldırırken upstream’in checkout güvenliği düzeltmelerini doğrudan izlemek zorundadır
-- ile --end-of-options arasındaki fark
- Genel Unix araçlarında
--, seçenek yorumlamanın bittiğini belirtir; bu yüzdenrm -- -f,-fdeğerini zorla silme seçeneği değil dosya adı olarak ele alır - Git ise erken dönemlerden beri
--işaretini revizyonlarla yol belirtimleri (pathspec) arasında ayırıcı olarak kullanırgit log foo,fooadlı bir branch’i mi yoksa dosyayı mı kastettiği konusunda belirsizdirgit log main -- README.md,mainüzerindeki commit’lerdenREADME.mddosyasına dokunanları ifade eder
- Bu tasarım nedeniyle revizyon konumunda seçenek sonlandırma işareti yoktu;
git log "$rev"içinde$revtireyle başlıyorsa Git bunu seçenek olarak yorumlar --end-of-optionsı getiren commit, mevcut--zaten revizyonlarla yol belirtimlerini ayırdığı için seçeneklerle revizyonları ayıracak ayrı bir işarete ihtiyaç olduğunu belirtir--end-of-options, gitcli(7) içinde belgelendi ve Git 2.24.0’ın yayımlandığı Kasım 2019’da eklendi
Komuta göre doğru kullanım
git clone -- "$url"komutunda,clonePOSIX geleneğini izlediği için URL’nin önündeki--seçenek yorumlamayı sonlandırırgit checkout "$ref" --içindeki sondaki--,$refdeğerini dosya adı değil revizyon olarak işaretler; ancak$refdeğerinin önce seçenek olarak yorumlanmasını engelleyemez- Güvenilmeyen revizyonu ve yolu birlikte güvenli biçimde geçirmek için
git log --end-of-options "$rev" -- "$path"gibi iki işareti de kullanmak gerekir--end-of-options, seçeneklerle revizyonları ayırır--, revizyonlarla yolları ayırır
- İki işaretin birbirinin yerine kullanılabileceğini varsaymak, tireyle başlayan girdileri engelleyemez
Alt komutlara göre farklı destek zamanları
--end-of-optionsdesteği tüm Git komutlarına tek seferde uygulanmadı; alt komut bazında eklendigit rev-parse, kendi argüman ayrıştırıcısını kullandığı için ilk eklenişinden 1 yıl sonra Git 2.30.0’da desteklemeye başladıgit checkoutvegit reset,--işaretini kendileri yorumlar; ilk uygulama--end-of-optionsı argüman listesinde bıraktığından bu komutlar onu reddetti- Bu sorun, Git 2.43.1’in yayımlandığı Şubat 2024’te çözüldü
Shell olmadan da oluşan argüman enjeksiyonu
- Git, Mercurial ve SSH’te çağıranın belirlediği komutu çalıştıran seçenekler resmi özellik olarak bulunur
git clone --upload-pack=<cmd>, sunucu tarafındaki ikiliyi belirtir- Tüm Git çağrılarındaki
-c core.sshCommand=<cmd>, bağlantı komutunu değiştirir - Mercurial’daki
--config=alias.<subcmd>=!<shell>, çalıştırılacak alt komutu isteğe bağlı bir shell betiğiyle yeniden tanımlar - SSH’teki
-oProxyCommand=<cmd>, proxy komutunu belirtir
- Bir sarmalayıcı program güvenilmeyen bir dizgeyi argüman listesine koyarsa bu özellikler saldırı aracına dönüşebilir
- Bu hata türü CWE-88 argüman enjeksiyonu (argument injection) kapsamına girer ve shell komut enjeksiyonundan farklıdır
- Program
system()yerineargvdizisi veexeckullansa da oluşur - Dizi bozulmadan Git’e aktarılır; ancak Git, tireyle başlayan argümanı seçenek olarak yorumlar
- Program
docker builddeki CVE-2019-13139, Go’nunos/execveargvdizisini kullanıp shell’den geçmeyen bir örnektir- Git context URL’sindeki
#ref:dirparçasıgit fetch origin <ref>komutuna aktarılırken<ref>,--upload-pack=<cmd>olarak yorumlandı
- Git context URL’sindeki
Birden fazla sürüm kontrol sisteminde tekrarlanan açıklar
- Ağustos 2017’de aynı gün dört sürüm kontrol sisteminde aynı kalıp açıklandı
- Git’te CVE-2017-1000117
- Mercurial’da CVE-2017-1000116
- Subversion’da CVE-2017-9800
- CVS’te CVE-2017-12836
- Dört sistemin tamamı URL’deki host adını SSH argümanı olarak aktarıyordu;
-oProxyCommand=ile başlayan host adı SSH seçeneği olarak işlendi - Phabricator olay sonrası analizine göre, o sırada aktif olarak bakımı yapılan üç araçtan yalnızca Subversion host adının önüne
--ekledi- Git ve Mercurial, tüm SSH uygulamalarının
--desteklememesi gibi nedenlerle host adı biçimini doğruladı
- Git ve Mercurial, tüm SSH uygulamalarının
--eksik olan kod da argüman tireyle başlayana kadar normal görünür ve çalışır; bu yüzden bu mekanizma temelde güvenli değildir
Paket yöneticilerinin maruz kaldığı yollar
- Paket yöneticileri manifest, lock dosyası ve geçişli bağımlılık metadata’sından Git URL’si ya da ref alıp alt süreçlere aktarır
- Gemfile’da
gem 'foo', git: '...' package.jsoniçindegithub:user/repo#refpyproject.toml,Cargo.toml,mix.exs,Package.swift,pubspec.yaml,conanfile.py,go.modiçindeki eşdeğer ayarlar
- Gemfile’da
- Temmuz 2026’daki HEAD baz alınarak incelenen 19 paket yöneticisinin 17’si, Git ikilisini varsayılan ya da tek yol olarak çalıştırıyor
- Kalan ikisi varsayılan olarak kütüphane kullanıyor
- Cargo libgit2 kullanır;
net.git-fetch-with-clietkinleştirilirse Git süreci çalıştırır - Poetry 1.2.0’dan itibaren dulwich’e geçti ve
system-git-clientayarıyla sistem Git’i kullanılabilir
- Cargo libgit2 kullanır;
- Nix, yerel depoyu okurken libgit2 kullanır; ancak libgit2 git-credential yardımcılarını desteklemediği için fetch için Git süreci çalıştırır
- İncelenenler Bundler, Cargo, CocoaPods, Composer, Conan, Go, Helm, Homebrew, Mix, Nix, npm, pip, pnpm, Poetry, Pub, SwiftPM, uv, vcpkg ve Yarn’dır
Paket yöneticilerinde doğrulanan CVE’ler
- Bu türde kamuya açıklanmış paket yöneticisi açıkları arasında şu örnekler bulunur
- Bundler’da CVE-2021-43809
- Composer’da CVE-2021-29472, CVE-2022-24828
- Poetry’de CVE-2022-36069
- pip’te CVE-2023-5752
- CocoaPods’ta CVE-2022-21223, CVE-2022-24440
- Go’da CVE-2025-68119
- Birden fazla 2022 açığını bulan Snyk, Git ve Mercurial’da argüman enjeksiyonu araştırmasını yayımladı
- Sonar, ikili bazında tehlikeli seçenekler listesini tutuyor
Gerçek savunma durumu ve Go’nun düzeltmesi
- Git süreci çalıştıran 17 paket yöneticisi içinde
--end-of-optionskullanan araç yalnızca Go’nuncmd/goaracıydı - Go, Haziran 2019’da genel bir savunma güçlendirmesi olarak depo URL’sinin önüne
--ekledi - Ocak 2026’da yalnızca
--kullanmanın yeterli olmadığı ortaya çıktı ve CVE-2025-68119 düzeltmesi kapsamında--end-of-optionsgenel olarak eklendi - Aynı düzeltme
HGPLAIN=+strictflagsayarını da içeriyordu- Bu ayar, Mercurial 4.4.2’nin yayımlandığı 2017’den beri Mercurial’ın ilk seçenek yorumlamasını sınırlar
- Go düzeltme commit’i, aynı sorunun yeniden eklenmesini zorlaştırmak için daha yapısal bir değişiklik gerekebileceğini, ancak şimdilik mevcut sorunu çözdüğünü belirtir
Savunmaların çoğu açıklar duyurulduktan sonra eklendi
- Kalan paket yöneticileri argüman listesini korusalar bile çoğunlukla
--ya da girdide baştaki tireyi reddetme yöntemini kullanır - Bundler’ın
git cloneURL’si önündeki--, CVE-2021-43809 yamasıyla eklendi - cocoapods-downloader’ın baştaki tireyi reddetmesi, CVE-2022-21223’ün açıklanma dönemiyle çakışan Mart 2022’deki on gün içinde üç commit ile uygulandı
- Poetry’nin savunması Eylül 2021’de eklendi; bir yıl sonra CVE atandı ve altı ay sonra dulwich’e geçildi
- vcpkg, istisnai olarak Git registry desteğinin yazıldığı ilk günden beri
--kullandı
Asgari Git sürümünün yarattığı uyumluluk kısıtları
- Composer’ın CVE-2022-24828 duyurusu,
--end-of-optionsı doğru düzeltme olarak işaret eder; ancak daha eski Git sürümlerini de desteklemek gerektiği için tireyle başlayan branch adlarını reddetme yolunu seçti - vcpkg’nin Git entegrasyonu asgari sürümü Git 2.7.4 olarak belirtir; Homebrew’ün Linux için
HOMEBREW_MINIMUM_GIT_VERSIONdeğeri ise 2018’de belirlenen 2.7.0’dır - Git 2.14.3 sağlayan Amazon Linux 2’nin Haziran 2026’da ömrünü tamamlamasıyla, bu alt sınırların takip ettiği dağıtımlar ancak şimdi destek kapsamından çıkıyor
- Ubuntu’nun uzun süreli destek durumu da toplu geçişi zorlaştırıyor
- Ubuntu 18.04, Git 2.17.0 sağlar ve 2028’e kadar uzatılmış destek kapsamındadır
- Ubuntu 20.04, Git 2.25.1 sağlar ve 2030’a kadar uzatılmış destek kapsamındadır
- Git 2.25.1,
git fetchiçin--end-of-optionsı kabul eder ancakgit rev-parseiçinde reddeder
--end-of-optionsa dayanmak için çoğu alt komutta asgari sürüm olarak Git 2.24.0,rev-parseiçin 2.30.0,checkoutveresetiçin 2.43.1 istemek gerekir- Asgari sürümü yükseltmek, dağıtımlarla gelen eski Git’i kullanan kullanıcıları destekleyememek anlamına gelir
Süreç çalıştırmak yerine Git kütüphanesi kullanmak
- libgit2, gitoxide, go-git, JGit ve dulwich, clone ve fetch için gereken Git aktarım protokollerini süreç içinde uygular
- Ayrı bir
argvsınırı olmadığı için argüman listesine enjekte edilecek hedefin kendisi yoktur - Jujutsu, Git entegrasyonu için gitoxide kullanır ve argüman enjeksiyonu türünde kamuya açık bir CVE’si yoktur
- Bugüne kadarki iki duyuru, path traversal ve kütüphaneden devralınan SHA-1 çakışma kontrolü eksikliğidir
- go-git’in CVE-2025-21613 açığı
file://aktarımıyla sınırlıdır- Bu yol, go-git içinde Git ikilisinin çalıştırıldığı tek kod yoludur
- Kendi Git uygulamanızı dahil etmek, upstream Git’in yayımladığı tüm checkout güvenliği düzeltmelerini izlemeyi gerektirir; libgit2 ve JGit’te bununla ilgili düzeltmelerin tekrarlandığı olmuştur
- Bu maliyet gerçektir; ancak her çağrı noktasında kalıcı olarak argüman kontrolünü hatırlamak yerine mesele, somut upstream yama akışını uygulamaya dönüşür
Homebrew’e önerilen değişiklik kapsamı
- Homebrew PR’ı, asgari Git sürümünü 2.30.0’a yükseltir ve şu konumlara
--end-of-optionseklerclone,remote set-url,ls-remoteiçinde URL’nin önünerev-parseiçinde ref’in önüne
checkoutveresetçağrıları değiştirilmez- Bu iki komutu da korumak için Şubat 2024’te yayımlanan Git 2.43.1 gerekir
- Bu sürüm, şu anda desteklenen birçok dağıtımın sağladığı Git’ten daha yenidir
1 yorum
Lobste.rs görüşleri
Özellikle bir
jjkomutunda öğrendiğiniz bilgi diğer komutlara da doğal biçimde uygulanıyor.git logbelgeleri, çıktı seçeneklerine göre bayrakların patlamasının yanı sıra commit aralığı sözdizimi olan “özel gösterim” ve ek filtre bayraklarıyla da iç içe geçmiş durumda; diğer Git komutlarına aktarılan bilgi de azBuna karşılık
jj logbelgeleri, tek sayfada bile boş yer kalacak kadar sade. Git’in ıvır zıvır türü karmaşıklığını revizyon kümeleri, dosya kümeleri ve çıktı şablonu DSL’i olmak üzere üç şeyle değiştiriyor; bunlar jj genelinde tutarlı biçimde kullanıldığı için çok daha basit, birleştirilebilir ve sezgisel. Git’in 20 yıldır fazlalık biriktirdiğini hesaba katmak gerekir ama jj bunu önlemek için çok daha elverişli görünüyor--gerektiğini biliyorum ama burada bir de kendine özgü dönüşüm kuralları istemek, gereksiz derecede tehlikeli bir tuzak oluyor--seçildiğini merak ediyorum. Dosyaları açık bir argüman olarak alan basit bir yaklaşım yerine bunun seçilmesinde görünmeyen bir tasarım ödünleşimi olup olmadığını sorguluyorum1990’lardaki Tcl ve Scheme tartışmalarına dönüp bakınca, bu durumda “daha kötü olan daha iyidir” yaklaşımı belki de doğruydu. JSON ve XML dâhil S-ifadesi ailesi UNIX ekosisteminde neredeyse hiç yer edinemezken, Tcl dizgelerin içine alt dilleri katmanlandıran nispeten ilkeli bir yaklaşıma sahipti