Bir depoya yazma erişimi olan her kullanıcı, o depoda tanımlı tüm secret'ları okuyabilir. Bu nedenle workflow'larınızın kullandığı kimlik bilgileri, işin izin verdiği en düşük yetkiyle çalışmalıdır. GitHub'ın güvenli kullanım referansı GITHUB_TOKEN için de aynı şeyi söyler: ona gereken minimum izinleri verin. Aşağıdaki beş görevin her biri bir gününüzü alır.
OWASP Top 10 CI/CD Security Risks listesi, bu planın dokunduğu sorun alanlarını adlandırır: yetersiz kimlik ve erişim yönetimi (CICD-SEC-2), bağımlılık zinciri istismarı (CICD-SEC-3), zehirlenmiş pipeline çalıştırma (CICD-SEC-4), yetersiz kimlik bilgisi hijyeni (CICD-SEC-6) ve yanlış artifact bütünlük doğrulaması (CICD-SEC-9).
Pazartesi: token'ın yapabileceklerini azaltın
Depoya push yapabilen herkesin secret'ları okuyabileceği varsayımından yola çıkın. Ardından bu kimlik bilgilerinin erişebildiği alanı daraltın.
GitHub, varsayılan GITHUB_TOKEN iznini depo içeriği için salt okunur olarak ayarlamanızı, ardından yalnızca gereken job'lar için yükseltmenizi önerir. Bir workflow dosyasında şöyle görünür:
permissions:
contents: read
jobs:
release:
permissions:
contents: write
Her workflow'u gözden geçirin ve hangi job'ların gerçekten bir şey yazdığını sorgulayın. Yazma erişimini yalnızca bu job'lara verin, gerisini okuma izninde bırakın.
Salı: kullandığınız action'ları denetleyin
Workflow'larınızda kullanılan her action'ı listeleyin; bakımını yaptığınız reusable workflow'lardan çağrılanlar da buna dahildir. Her biri için action'ın kaynak kodunu ve onu çalıştıran deponun kaynağını okuyun.
GitHub'ın secret denetimi rehberi nelere bakılacağı konusunda nettir. Secret'ların istenmeyen host'lara gönderilmediğini ve log çıktısına açıkça yazdırılmadığını kontrol edin.
Ardından en az yetki ilkesini kimlik bilgilerinin kendisine uygulayın. Depoya yazma erişimi, secret'lara okuma erişimi anlamına geldiği için bir workflow'un kullandığı her kimlik bilgisi yalnızca o workflow'un ihtiyaç duyduğu işi yapabilmelidir. Tüm bulut hesabını yönetebilen bir deploy token'ı bu ölçütü karşılamaz.
Çarşamba: script injection
Pull request başlığı gibi güvenilmeyen context değerleri, doğrudan inline script içine yerleştirildiklerinde sorun yaratır. GitHub'ın referansı bundan kaçınmak için iki yol sunar.
Önerilen yaklaşım, context değerini argüman olarak alan bir action kullanmaktır; çünkü bu durumda değer hiçbir zaman bir shell script üretmek için kullanılmaz. Inline script kullanmak zorundaysanız ifadeyi ara bir ortam değişkenine atayın:
- name: Check PR title
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ "$TITLE" =~ ^octocat ]]; then exit 0; else exit 1; fi
GitHub'ın örneğinde a"; ls $GITHUB_WORKSPACE" başlığı kontrolden geçemez ve komut çalıştırılmaz. Değer bellekte tutulur ve değişken olarak kullanılır, bu yüzden script üretimiyle etkileşime girmez. GitHub ayrıca word splitting'i önlemek için shell değişkenlerinin çift tırnak içine alınmasını önerir; bu genel bir shell pratiğidir.
Aday noktaları bulmak için workflow'larınızda context ifadelerini arayın ve her sonucu run: bloğunun içinde okuyun:
grep -rn 'github.event' .github/workflows
Perşembe: secret'lar ve korumalı environment'lar
Deployment secret'larını environment'lara koyun ve onay verecek reviewer'ları zorunlu kılın. Bir workflow job'ı, reviewer onaylayana kadar environment secret'larına erişemez.
GitHub, otomatik redaction'ın garanti edilmediğini açıkça belirtir; çünkü bir secret değeri birçok biçimde dönüştürülebilir. Redaction büyük ölçüde birebir eşleşme bulmaya dayanır ve runner tarafından yapılır. Dolayısıyla bir secret yalnızca bir job onu kullanmışsa ve runner ona erişebilmişse maskelenir. İnceleme için şu tabloyu kullanın:
| İncelenecek öğe | Yanıtlanacak soru |
|---|---|
| Kayıtlı secret'lar | Her biri hâlâ gerekli mi ve en son ne zaman rotasyona alındı? |
| Yapılandırılmış secret'lar | Herhangi bir secret JSON, XML veya YAML blobu mu? Her değer için ayrı bir secret olacak şekilde bölün. |
| Türetilmiş değerler | Base64 veya URL ile kodlanmış ya da üretilmiş her değer (örneğin imzalı bir JWT) secret olarak kaydedildi mi? |
| Diğer hassas veriler | GitHub secret'ı olmayan veriler ::add-mask::VALUE ile maskeleniyor mu? |
| Çalıştırma logları | Geçerli ve geçersiz girdilerle test ettikten sonra secret'lar çıktıda veya hata loglarında görünüyor mu? |
| Environment'lar | Production secret'ları zorunlu reviewer'ların arkasında mı? |
Hatalar STDOUT ve STDERR'e planlamadığınız yollarla ulaşabilir, bu yüzden testlerden sonra logları elle okuyun. Maskelenmemiş bir secret bir çalıştırma loguna düşerse logu silin ve secret'ı rotasyona alın. Artık ihtiyaç duyulmayan secret'ları kaldırın, kalanları periyodik olarak rotasyona alın; bu, ele geçirilmiş bir değerin geçerli kaldığı süreyi kısaltır.
Cuma: workflow'ların ve çıktıların sahipliği
Bu bölüm bizim tavsiyemizdir. Yukarıdaki kaynaklar bunu öngörmez ve GitHub, OWASP ya da NIST'e atfedilmez.
Yazılımınızı derleyen ve yayınlayan workflow'larda kimlerin değişiklik yapabileceğine karar verin ve bunu yazılı hale getirin. Platformunuzda CODEOWNERS kullanıyorsanız .github/workflows dizini kapsanması mantıklı bir yoldur. Ardından, müşterilerin veya production sistemlerinin güveneceği şey release artifact'ları olduğu için hangi workflow'un bu artifact'ları ürettiğini belirleyin.
Kaynaklar artifact konusunda yalnızca kısmen yol gösterir. OWASP, yanlış artifact bütünlük doğrulamasını CICD-SEC-9, yetersiz loglama ve görünürlüğü ise CICD-SEC-10 olarak listeler. NIST'in Secure Software Development Framework (SP 800-218) çerçevesi, alıcıların ve tedarikçilerin güvenli geliştirmeyi tartışırken kullanabileceği ortak bir sözlük sağlar. Hiçbiri bir imzalama reçetesi sunmadığı için biz de burada bir tarif vermiyoruz.
Son olarak, workflow dosyaları, secret'lar veya environment onayları değiştiğinde bunu kimin fark edeceğine ve nasıl haberdar olacağına karar verin.
Nereden başlamalı
- Varsayılan
GITHUB_TOKENiznini depo içeriği için salt okunur olarak ayarlayın ve daha fazlasına ihtiyaç duyan job'larapermissionsblokları ekleyin. - Kullanılan tüm action'ları listeleyin, kaynak kodlarını okuyun ve secret'ları beklenmedik host'lara göndermediklerini ya da loglara yazdırmadıklarını doğrulayın.
run:blokları içindeki context ifadelerini arayın ve bunları ara bir ortam değişkenine ya da bir action'a taşıyın.- Production secret'larını zorunlu reviewer'lı bir environment'a taşıyın, yapılandırılmış secret'ları tek değerlere bölün, türetilmiş değerleri kaydedin ve bir logda görünmüş her şeyi rotasyona alın.
- Release artifact'larını derleyen workflow'ları kimlerin değiştirebileceğini ve değişiklik olduğunda kimin bilgilendirileceğini yazılı hale getirin.
Pipeline'larınız hakkında ikinci bir görüş almak isterseniz güvenli yazılım geliştirme hizmetimiz CI/CD yapılandırmasını da kapsar. Bir sızma testi ise bir pull request'in secret'larınıza ulaşıp ulaşamayacağını gösterebilir.
