Self-hosted CI runner, hız ve kontrol sağlar: daha hızlı build, özel network erişimi, maliyet optimizasyonu… Ama aynı zamanda en kolay suistimal edilen yürütme yüzeylerinden biridir. Çünkü CI job’ı, pratikte “sizin adınıza kod çalıştırma” yetkisi alır.
Bu yazı, GitHub Actions gibi sistemlerde self-hosted runner kullanan ekipler için, sahada en çok fark yaratan üç ekseni bir araya getirir:
- İzolasyon (runner’ın “tek seferlik” ve sınırlı olması)
- OIDC (statik secret yerine kısa ömürlü erişim)
- Secret disiplini (deploy yetkisini ayrıştırmak)
1) Tehdit modeli: Runner’da ne yanlış gidebilir?
Self-hosted runner için pratik tehdit modeli:
- Pull request ile keyfi komut çalıştırma
- Runner’dan ağ keşfi (internal scan)
- Artifact veya cache üzerinden backdoor taşıma
- Deploy credential’larını sızdırma
- Runner host’u kalıcı ele geçirme (persistence)
2) Birincil kontrol: Runner’ı kalıcı değil, geçici tasarla
En sağlam model: ephemeral runner.
Pratik seçenekler:
- Her job için yeni VM/instance aç, job bitince imha et
- Container runner kullanıyorsan: “privileged yok”, host mount yok, node paylaşımsız
- Cache’i “repo bazlı” ve sınırlı tut, cross-repo paylaşımı azalt
Amaç: saldırgan runner’a girse bile kalıcılık kuramasın.
3) Ağ sınırı: Runner’ın egress’i “default deny” olmalı
Self-hosted runner çoğu kurumda şuraya erişir:
- artifact registry
- package repo
- container registry
- deploy API (cloud, k8s, etc.)
Risk: “internal her yere çıkabilen” runner, lateral movement için altın bilettir.
Minimum pratik:
- Runner subnet’i ayrı olsun
- Egress allowlist: yalnızca gerekli domain/IP/port’lar
- DNS log + proxy log ile “beklenmeyen çıkış” alarmı
4) Secret stratejisi: Build ile deploy’u ayır
Runner’ı güvenli tasarlamanın en hızlı kazanımı:
- Build runner: kodu derler/test eder, deploy yetkisi yok
- Deploy runner: sadece
main/tag ve onay sonrası çalışır, daha kısıtlı ve izlenir
Eğer aynı runner hem PR build hem prod deploy yapıyorsa, bir gün PR üzerinden prod anahtarlarını taşırsınız. Genelde fark edilmez; ta ki olay olana kadar.
5) OIDC: Statik anahtarları CI’dan çıkar
Statik cloud key’leri (access key/secret) CI secret store’da duruyorsa:
- sızar
- unutulur
- rotasyon yapılmaz
OIDC ile yaklaşım:
- CI job’ı kısa ömürlü bir kimlik token’ı alır
- Cloud tarafında bu kimlik “sadece şu repo/branch/job için” yetkilendirilir
- Token süresi bittiğinde erişim biter
Operasyonel kazanım: Rotasyon işi azalır, audit izi güçlenir, yetki daha daralır.
6) Minimum viable runner güvenlik kontrol listesi
- Ephemeral runner veya “temiz imaj + sık reset” modeli var
- PR job’ları deploy yetkisi almıyor
- Deploy job’ları korunmuş branch/tag + onay ile çalışıyor
- Runner egress allowlist (default deny)
- OIDC ile kısa ömürlü yetkilendirme
- Token izinleri minimum (repo token permissions dar)
- Artifact imzalama / checksum doğrulama
- Runner log + network log + audit log korelasyonu
Self-hosted runner güvenliği, tek bir ayar değil; izolasyon + yetki ayrımı + kısa ömürlü kimlik kombinasyonudur. Bu üçlü bir araya geldiğinde CI, kurum içinde “gizli admin makinesi” olmaktan çıkar ve yönetilebilir bir otomasyon yüzeyine dönüşür.