Mert Özen Her Satırda Daha İleri
Güvenlik DevSecOps — #01

DevSecOps Nedir? Güvenlik Kontrollerini Pipeline'ın Doğru Yerine Koymak

Mert Özen 14 Kas 2026 14 dk 4 görüntülenme
DevSecOps Nedir? Güvenlik Kontrollerini Pipeline'ın Doğru Yerine Koymak

DevSecOps, güvenlik kontrollerini pipeline'da ihtiyaç duydukları bilginin ilk ortaya çıktığı yere koymak ve bulguyu kodu yazan ekibe o anda döndürmektir: secret pre-commit'te, SAST ve SCA PR'da, image taraması main'de, DAST deploy'dan sonra. Bookstore pipeline'ının önce/sonra haritasını çıkarıyor, Semgrep baseline ile yalnız yeni bulguyu kırmayı gerçek çıktılarla gösteriyor ve kontrolleri NIST SSDF ile OWASP DSOMM'a eşliyoruz.

Sürüm notu: Bu yazıdaki kodlar .NET 10 ile derlenip denenmiştir; workflow actionlint 1.7.12 ile doğrulanmış, taramalar Semgrep 1.168 ve gitleaks 8.30.1 ile çalıştırılmıştır.

Önce Tahmin Et

Bookstore ekibi bir sprint'te "güvenliği pipeline'a ekleyelim" kararı alıyor. Bir geliştirici aynı gün SAST (kaynak kodu çalıştırmadan tarayan güvenlik testi), SCA (bağımlılıklardaki bilinen zafiyetleri ve lisansları tarayan analiz), image taraması ve DAST (çalışan uygulamaya dışarıdan saldırarak yapılan güvenlik testi) adımlarını workflow'a ekliyor, hepsini en düşük severity'den itibaren build'i kıracak şekilde ayarlıyor. İlk koşuda yüzlerce bulgu çıkıyor; çoğu yıllardır kodda duran eski sorunlar, bir kısmı false positive. Tahmin et: iki hafta sonra bu pipeline nasıl görünür?

Çoğu ekipte sonuç aynıdır: adımların yanında continue-on-error: true belirmiştir, ya da biri "geçici olarak" job'ı yorum satırına almıştır. Kimse kötü niyetli değil; ekip, her PR'ı kendisinin yazmadığı yüzlerce bulgu yüzünden kırmızı gören bir kontrolü haklı olarak gereksiz uyarı kaynağı sayar. DevSecOps'un zor tarafı araç kurmak değil, kontrolleri doğru yere, doğru eşikle ve doğru sırayla koymaktır. Bu yazı serinin haritası: hangi kontrol pipeline'ın neresinde durur, neden orada durur, ve gereksiz uyarıları nasıl bir sınır içinde tutarsın.

DevSecOps Aslında Ne?

DevSecOps (Development, Security, Operations), DevOps'un kısa geri bildirim döngüsüne güvenliği ekleme fikridir. Bir ürün ya da ayrı bir ekip değildir. Pratikte üç şey anlamına gelir: güvenlik kontrolleri otomatiktir ve pipeline'da çalışır, bulgular kodu yazan ekibe kodu yazdığı anda döner, ve düzeltmenin sahibi o ekiptir. Merkezdeki güvenlik ekibi kuralları ve eşikleri belirler, araçları bakımda tutar; ama bulguyu kapatan PR'ı uygulamayı yazan ekip açar.

"Shift-left" terimi test dünyasından gelir; Larry Smith'in Dr. Dobb's Journal'da Eylül 2001'de yayımlanan "Shift-Left Testing" yazısına atfedilir. Fikir basit: bir hatayı yaşam döngüsünde ne kadar erken yakalarsan düzeltmesi o kadar ucuzdur. Güvenlikte bunun karşılığı, secret'ı commit'ten önce, SQL injection'ı PR'da yakalamaktır. Ama tek başına shift-left eksik kalır. Bazı riskler ancak sağda görünür: bugün temiz geçen bir image'da yarın yeni bir CVE (yayımlanmış güvenlik açıklarının standart kimlik numarası) yayımlanır, yanlış bir configuration ancak çalışan ortamda ortaya çıkar. Bu yüzden "shift-right" da gerekir: registry'de sürekli tarama, runtime monitoring ve yeni bir zafiyette "bu bizi etkiliyor mu?" sorusunu hızla cevaplayan bir envanter. İkisi rakip değil, aynı hattın iki ucu.

Her Kontrolün Bir Yeri Var

Bir kontrolün yerini üç soru belirler. Birincisi, kontrolün ihtiyaç duyduğu bilgi ilk nerede ortaya çıkıyor? SAST kaynak koda ihtiyaç duyar, PR'da hazırdır; image taraması image'a ihtiyaç duyar, build'den önce yoktur; DAST çalışan bir uygulamaya ihtiyaç duyar, deploy'dan önce yoktur. İkincisi, bulguyu kim, ne kadar ucuza düzeltebilir? PR'daki bulguyu yazan kişi aynı branch'te on dakikada düzeltir; production'da bulunan aynı bulgu bir incident, bir hotfix ve bir release demektir. Üçüncüsü, kontrol o aşamanın süre bütçesine sığıyor mu? Yirmi dakikalık aktif bir DAST taraması her PR'da çalışırsa ekip ya PR açmayı erteler ya da taramayı kapatır.

Secret'ın yeri bu soruların en net örneği. Bir secret push edildiği anda sızmış sayılır: Git geçmişinde, fork'larda, CI cache'lerinde ve klonlarda yaşamaya devam eder. Bu yüzden secret kontrolü mümkün olan en sola, geliştirici makinesine ve push anına konur; sağdaki tarama yalnızca kaçanı yakalayan bir ağdır.

01-control-placement-tr.png

AşamaKontrolNeden buradaBookstore'da davranış
IDE.NET analyzer'ları (CA5xxx), SAST eklentisiKod yazılırken en ucuz geri bildirimUyarı, kırmaz
pre-commitSecret taraması (gitleaks)Secret commit'e girmeden durmalıCommit'i durdurur
Pull requestSecret, SCA (yeni bağımlılık), SAST (yeni bulgu)Kaynak kod ve diff hazır, yazar ortadaYalnız yeni bulgu kırar
main buildImage ve IaC (Infrastructure as Code) taraması, SBOM (yazılımın içerdiği bileşenlerin listesi), imzaImage ve manifest ancak build'den sonra varFix'i olan critical/high kırar
Deployİmza doğrulama, staging'de DASTÇalışan uygulama ve deploy edilecek artifact buradaİmzasız artifact reddedilir, DAST raporlar
RuntimeRegistry taraması, SBOM ile CVE eşleştirme, monitoringYeni zafiyetler release'ten sonra yayımlanırAlarm ve backlog kaydı

Tablodaki "kırar" ile "raporlar" ayrımı bilinçli. Her kontrol bir gate olmak zorunda değil; bir kontrolün işi bazen sadece görünürlük sağlamaktır. Gate'i yalnızca bulgunun düzeltilebilir ve yüksek riskli olduğu yerde, düzeltmesi PR sahibinin elinde olduğu sürece kullanırsın.

Bookstore Pipeline'ı: Önce ve Sonra

CI/CD Temelleri ve GitHub Actions serilerinde Bookstore için kurduğumuz workflow restore, build ve test yapıyordu; güvenlik açısından tek kontrolü NuGetAudit uyarılarıydı. NuGetAudit, npm audit ve SRI'ı (Subresource Integrity) OWASP (web uygulama güvenliği üzerine çalışan açık topluluk) serisinin "OWASP A03: Software Supply Chain Failures — NuGetAudit, npm audit ve SRI" yazısında anlattık; Bookstore'da bu uyarılar yalnızca log'da kalıyordu. Aşağıdaki iskelet "sonra" halinin yerleşimini gösteriyor: hangi job hangi event'te çalışıyor, hangisi kırıyor, hangisi rapor üretiyor. Araçların kurulum adımları, job'lar arası artifact aktarımı ve ayarların detayı bilinçli olarak dışarıda; her biri serinin ilgili yazısında açılıyor, tamamı son yazıda tek workflow'da birleşiyor.

name: bookstore-ci

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  # PR ve main: hızlı kontroller
  secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          fetch-depth: 0
      # gitleaks kurulumu ve geçmiş taraması: 2. yazı
      - run: gitleaks git --redact --exit-code 1 .

  dependencies:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
        with:
          dotnet-version: 10.0.x
      # NU1903 (high) ve NU1904 (critical) restore'u kırar: 3. yazı
      - run: dotnet restore Bookstore.slnx -warnaserror:NU1903,NU1904
      - run: npm ci --prefix web
      - run: npm audit --prefix web --audit-level=high

  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
        with:
          fetch-depth: 0
      # yalnız bu PR'ın eklediği bulgular kırar: 4. yazı
      - if: github.event_name == 'pull_request'
        run: semgrep scan --config p/csharp --error --baseline-commit "origin/$BASE_REF"
        env:
          BASE_REF: ${{ github.base_ref }}
      # main: tam tarama rapor olarak, eski bulgular backlog'a
      - if: github.event_name == 'push'
        run: semgrep scan --config p/csharp --sarif --output semgrep.sarif

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - uses: actions/setup-dotnet@0f4a354dd5547a28c70b7853dbd95d5b67886e73 # v6.1.0
        with:
          dotnet-version: 10.0.x
      - run: dotnet build Bookstore.slnx -c Release
      - run: dotnet test Bookstore.slnx -c Release --no-build

  # yalnız main: yavaş ve derin kontroller
  image:
    if: github.event_name == 'push'
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - run: docker build -t "bookstore-api:$GITHUB_SHA" -f src/Bookstore.Api/Dockerfile .
      # image taraması: 5. yazı, SBOM: 7. yazı
      - run: trivy image --exit-code 1 --severity CRITICAL,HIGH --ignore-unfixed "bookstore-api:$GITHUB_SHA"
      - run: syft "bookstore-api:$GITHUB_SHA" -o cyclonedx-json=sbom.cdx.json

  dast:
    if: github.event_name == 'push'
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      # ephemeral environment + pasif ZAP taraması: 6. yazı
      - run: docker compose up -d --wait
      - run: docker run --rm --network host ghcr.io/zaproxy/zaproxy:stable zap-baseline.py -t http://localhost:8080

Yerleşimdeki kararlar şunlar. secrets, dependencies ve sast build ile paralel çalışıyor; birbirini beklemiyorlar, PR'ın toplam süresi en yavaş job kadar. Branch protection ya da ruleset'te bu dört job'ı required status check yaparsın; sıralı needs zinciri kurmak yalnızca süreyi uzatır. image ve dast yalnızca main'e push'ta çalışıyor çünkü ikisi de daha yavaş ve ikisi de PR yazarının tek başına düzeltemeyeceği bulgular üretebiliyor; base image'daki bir OS paketi zafiyeti, PR'daki diff'le ilgili değildir. sast job'ı iki modda çalışıyor: PR'da yalnız yeni bulgu kırıyor, main'de tam tarama SARIF (statik analiz sonuçları için standart JSON formatı) raporu olarak kalıyor. github.base_ref değerinin run satırına doğrudan değil environment variable üzerinden girmesi ve action'ların tam commit SHA'sıyla (yaygın kullanılan hash algoritması ailesi) sabitlenmesi "GitHub Actions Güvenliği: SHA Pinning, Lockfile, pull_request_target ve Script Injection'dan Korunmak" yazısının kuralları; burada tekrar etmiyoruz.

İskeleti çalıştırmadan önce yapısal olarak doğrulamak için actionlint kullandım:

actionlint
echo $?
0

Çıktı yok, exit code 0: syntax, expression'lar, needs referansları ve if koşulları tutarlı. actionlint workflow'un doğru çalışacağını kanıtlamaz, ama bir yazım hatasının main'e kadar fark edilmemesini engeller.

Uyarı Bütçesi: Yeni Bulguyu Engelle, Eskiyi Backlog'a Al

Her kontrolün bir uyarı bütçesi vardır: ekibin kontrolü kapatmadan önce katlanabileceği false positive ve "benim sorunum değil" bulgu miktarı. Bu bütçeyi aşan bir gate er geç devre dışı kalır, ve devre dışı bir gate hiç olmayan bir gate'ten daha kötüdür, çünkü herkes korunduğunu sanır. Bütçeyi korumanın en etkili kuralı şu: yeni bulguyu engelle, mevcut bulguyu backlog'a al.

Bookstore'da bunu Semgrep'le deneyelim. main branch'inde 2019'dan kalma, string birleştirmeyle SQL kuran bir SearchByTitle method'u var. Yeni bir branch'te birisi yazar adına göre arama ekliyor ve aynı hatayı interpolated string ile tekrar yapıyor:

public List<string> SearchByAuthor(string author)
{
    using var connection = new SqlConnection(connectionString);
    connection.Open();
    using var command = new SqlCommand(
        $"SELECT b.Title FROM Books b JOIN Authors a ON a.Id = b.AuthorId WHERE a.Name = '{author}'",
        connection);
    using var reader = command.ExecuteReader();
    var titles = new List<string>();
    while (reader.Read())
    {
        titles.Add(reader.GetString(0));
    }
    return titles;
}

Branch üzerinde tam tarama iki bulgu verir; biri bu PR'ın, biri 2019'un:

semgrep scan --config p/csharp --metrics=off
 • Findings: 2 (2 blocking)
Ran 27 rules on 2 files: 2 findings.

PR'ı bu sonuca göre kırarsan, yazar kendi yazmadığı bir method yüzünden bekler. --baseline-commit ile Semgrep önce main'deki durumu tarar, oradaki bulguları sonuçtan çıkarır:

semgrep scan --config p/csharp --metrics=off --error --baseline-commit main
echo $?
Creating git worktree from 'main' to scan baseline.
 • Findings: 1 (1 blocking)
 • Scan was limited to files changed since baseline commit.
Ran 27 rules on 2 files: 1 finding.

    src/Bookstore.Api/BookQueries.cs
   ❯❯❱ csharp.lang.security.sqli.csharp-sqli.csharp-sqli
          ❰❰ Blocking ❱❱
          Detected a formatted string in a SQL statement. This could lead to SQL injection if variables in the
          SQL statement are not properly sanitized. Use a prepared statements instead. You can obtain a
          PreparedStatement using 'SqlCommand' and 'SqlParameter'.
          Details: https://sg.run/d2Xd

           29┆ $"SELECT b.Title FROM Books b JOIN Authors a ON a.Id = b.AuthorId WHERE a.Name =
               '{author}'",
1

Artık yalnızca satır 29 raporlanıyor ve exit code 1 PR'ı kırıyor. Yazar sorgusunu parametreye çeviriyor:

using var command = new SqlCommand(
    "SELECT b.Title FROM Books b JOIN Authors a ON a.Id = b.AuthorId WHERE a.Name = @author",
    connection);
command.Parameters.Add("@author", SqlDbType.NVarChar, 200).Value = author;
Creating git worktree from 'main' to scan baseline.
 • Findings: 0 (0 blocking)
 • Scan was limited to files changed since baseline commit.
Ran 27 rules on 2 files: 0 findings.

Satır 15'teki eski bulgu ortadan kalkmadı; sadece bu PR'ın sorumluluğu değil. main'deki tam tarama onu her seferinde raporlamaya devam eder ve onun için sahibi ve hedef tarihi olan bir backlog kaydı açılır. Burada önemli bir ayrıntı var: baseline mekanizması bulguyu satırın içeriğiyle eşleştirir. Denemede eski satırdaki LIKE '% ifadesini LIKE N'% yapınca satır 15 de "yeni" bulgu olarak geri geldi. Bu iyi bir davranış: eski koda dokunan, oradaki bulgunun da sahibi olur. "Kamp alanını bulduğundan temiz bırak" kuralı böylece otomatik işler.

Bütçeyi koruyan diğer ayarlar seri boyunca tekrar edecek: severity eşiği (critical ve high kırar, medium raporlanır), yalnızca fix'i olan zafiyette kırmak, kural setini Bookstore'a göre budamak ve her istisnaya bir gerekçe, bir sahip ve bir bitiş tarihi koymak. İstisna yönetimini ve ölçümü serinin son yazısında uçtan uca kuruyoruz.

Kim Düzeltir? Sorumluluk Paylaşımı

Araçlar bulgu üretir; bulguyu kapatan insanlardır. İşleyen bir model genellikle şöyle görünür. Merkezi güvenlik ekibi (AppSec, Application Security) kural setlerini, eşikleri ve istisna politikasını belirler, araçların sürümünü ve kendi güvenliğini yönetir. Her ürün ekibinde bir security champion bulunur: güvenlik uzmanı olması gerekmeyen, ama bulgunun gerçek mi false positive mi olduğunu ilk değerlendiren, ekibine kuralları anlatan ve AppSec ile köprü kuran bir geliştirici. Düzeltmenin sahibi ise her zaman kodun sahibi olan ekiptir.

Bunu teknik olarak da desteklemek gerekir. Workflow dosyaları, Semgrep kural dosyası ve suppression listeleri CODEOWNERS ile korunursa, bir geliştirici bir gate'i kendi PR'ında sessizce gevşetemez; değişiklik security champion'ın review'una düşer. Bulgular ekibin kendi iş takip sistemine akmalı; ayrı bir güvenlik portalında bekleyen bulguyu kimse açıp bakmaz.

Çerçeveler: SSDF, SAMM ve DSOMM Haritası

Bu kontrolleri sıfırdan icat etmiyoruz; üç çerçeve ortak dil sağlıyor. NIST'in (ABD'nin ulusal standartlar ve teknoloji enstitüsü) SSDF'i (Secure Software Development Framework, SP (NIST'in teknik yayın dizisi) 800-218) Şubat 2022'de yayımlanan 1.1 sürümüyle güncel; pratikleri dört gruba ayırır: organizasyonu hazırlamak (PO, Prepare the Organization), yazılımı korumak (PS, Protect the Software), iyi korunan yazılım üretmek (PW, Produce Well-Secured Software) ve zafiyetlere yanıt vermek (RV, Respond to Vulnerabilities). SSDF'in 1.2 sürümü (SP 800-218 Rev. 1) Aralık 2025'te taslak olarak yayımlandı ve yorum dönemi Ocak 2026'da kapandı; bu yazı yazılırken NIST sayfasında hâlâ taslak görünüyor, o yüzden 1.1'e göre eşliyoruz.

OWASP SAMM (OWASP'ın yazılım güvenliği olgunluk modeli) 2.0, beş iş fonksiyonu (Governance, Design, Implementation, Verification, Operations) altında on beş pratik ve her pratik için üç olgunluk seviyesi tanımlar; bu serinin konusu ağırlıkla Implementation altındaki Secure Build ve Defect Management ile Verification altındaki Security Testing pratiklerine düşer. OWASP DSOMM (DevSecOps Maturity Model) ise doğrudan pipeline'a bakar: Build and Deployment, Culture and Organization, Implementation, Information Gathering ve Test and Verification boyutlarında, beş seviyeye yayılmış somut etkinlikler listeler. Aşağıdaki tablo serinin yazılarını SSDF pratiklerine ve DSOMM etkinliklerine eşliyor; parantezdeki sayı DSOMM'daki seviye.

YazıSSDF 1.1DSOMM etkinliği (seviye)
2. Secret scanningPS.1, PW.7Test for stored secrets in code (1)
3. Dependency scanning ve önceliklendirmePW.4, RV.1, RV.2Software Composition Analysis (server side) (2), Exploit likelihood estimation (2)
4. SASTPW.7Static analysis for important server side components (3)
5. Container ve IaC scanningPW.7, RV.1Test of virtualized environments (2), Test the definition of virtualized environments (2)
6. DASTPW.8Simple Scan (2), Usage of different roles (2)
7. SBOM ve VEX (bir zafiyetin üründe gerçekten istismar edilebilir olup olmadığını bildiren doküman)PS.3SBOM of components (2), Inventory of production dependencies (3)
8. İmzalama ve provenancePS.2Signing of artifacts (5)
9. Gate'ler, istisnalar, ölçümPO.4, RV.2Treatment of defects with high or critical severity (1), Simple false positive treatment (1)

Tablodaki seviyeler sıralama için de ipucu veriyor: DSOMM, kodda secret testini birinci seviyeye, artifact imzalamayı beşinci seviyeye koyuyor. Bu bir değer yargısı değil, bir bağımlılık sırası: imzalanmış bir artifact'ın içinde hâlâ sızmış bir connection string varsa imza sana yalnızca o secret'ın kimden geldiğini kanıtlar.

Sıralama: Her Şeyi Aynı Anda Açma

Önce Tahmin Et'teki ekibin hatası araç seçimi değil, sıralamaydı. Bookstore için önerdiğim sıra şöyle. Önce secret scanning ve SCA: ikisinin de false positive oranı düşüktür, bulguları açık ve aksiyonu belli (secret'ı rotate et, paketi güncelle), ve sömürülmesi en kolay risklere karşılık gelirler. Sonra SAST, ilk günden baseline ile: yalnızca yeni bulgu kırar, eski bulgular backlog'a gider ve ekip kural setine birkaç sprint boyunca alışır. Ardından image ve IaC taraması, main'de ve yalnız fix'i olan critical/high için kırarak. En son DAST: çalışan bir ephemeral environment, test kullanıcısı ve bakımlı bir rules dosyası ister, ilk aylarda rapor modunda kalması normaldir. SBOM ve imza bu sıranın yanında paralel ilerleyebilir; kimseyi kırmazlar ama release sürecine yeni adımlar eklerler.

Ne zaman DevSecOps araçlarını kurmamalısın? Bir ekip zaten dolu bir güvenlik backlog'unu işleyemiyorsa, ona yeni bir tarayıcı vermek backlog'u büyütmekten başka bir işe yaramaz. Önce mevcut bulguların sahibini ve işleme kapasitesini kur, sonra kontrol ekle.

Üretimde Dikkat

Pipeline'a eklediğin her tarayıcı, secret'larına ve artifact'larına erişen yeni bir yazılımdır. Mart 2026'da Trivy'nin GitHub Action tag'lerinin kötü niyetli commit'lere yönlendirilmesi bunun somut örneğiydi; ayrıntısına ve korunma yollarına serinin beşinci yazısında bakıyoruz. Tarayıcı action'larını tam SHA'yla sabitle, job'lara yalnız ihtiyaç duydukları permissions'ı ver ve tarayıcı binary'lerini checksum ile doğrula.

Süre bütçesini ölç. Bookstore'un küçük repo'sunda baseline'lı Semgrep taraması iki saniyenin altında, gitleaks taraması 80 milisaniye civarında sürdü; gerçek bir repo'da bu sayılar büyür. PR kontrollerinin toplamı birkaç dakikayı geçmeye başladığında paralelleştir, cache kullan ya da derin taramayı main'e taşı. Pipeline hızını DORA (DevOps Research and Assessment) metrikleriyle ölçmenin genel yöntemleri CI/CD Temelleri serisinin "Pipeline'ı Ölçmek ve Hızlandırmak: DORA Metrikleri, Cache ve Paralellik" yazısında.

Son olarak, bulguların nereye aktığını baştan karar ver. SARIF çıktısını GitHub'ın code scanning sekmesine yüklemek, bulguyu PR'da satır üzerinde annotation olarak gösterir ve geçmişini tutar; log'da kalan bulgu ise pratikte yok sayılır.

Sık Düşülen Tuzaklar

Birincisi, her aracı ilk günden en düşük eşikle gate yapmak. Sonuç kapatılan bir gate'tir. Önce rapor modunda ölç, sonra eşiği kademeli olarak sıkılaştır.

İkincisi, baseline'ı halı altına süpürmek için kullanmak. Baseline yalnızca "bu PR'ın sorumluluğu değil" demektir; eski bulgular için sahibi ve tarihi olan bir backlog kaydı yoksa sadece görünmez hale getirmiş olursun.

Üçüncüsü, güvenlik kontrollerini yalnızca main'de çalıştırmak. Bulgu main'de çıktığında yazar başka işe geçmiştir ve düzeltme pahalanır. Hızlı ve kesin kontroller PR'a aittir.

Dördüncüsü, araç çıktısını tek ölçü saymak. SAST iş mantığı hatasını, SCA yanlış yazılmış bir authorization kontrolünü bulmaz; code review, threat modeling ve API Güvenliği serisinin "API Güvenliğini Sürekli Test Etmek ve İzlemek: Authorization Regresyonu, OpenAPI Tabanlı Tarama ve Abuse Telemetry" yazısındaki gibi authorization regresyon testleri yerinde durur.

Küçük Bir Deneme

★☆☆ Kendi projendeki CI workflow'unu aç ve her güvenlik kontrolünü tablodaki aşamalardan birine yerleştir. Hiç kontrol olmayan aşamaları ve "kırar" mı "raporlar" mı belli olmayan adımları not et.

★★☆ Bir .NET projesinde semgrep scan --config p/csharp --metrics=off ile tam tarama yap, sonra yeni bir branch'te küçük bir değişiklik yapıp aynı taramayı --baseline-commit main ile tekrarla. İki sayı arasındaki farkı ve hangi bulguların backlog'a gitmesi gerektiğini yaz.

★★★ Ekibin için tek sayfalık bir "kontrol yerleşim politikası" taslağı çıkar: her kontrol için aşama, kıran eşik, istisna sahibi ve hedef süre. SSDF 1.1'deki PO.4 pratiğiyle karşılaştır ve eksik kalan maddeyi bul.

Haritayı çizdik; bir sonraki yazıda en soldaki ve en acil kontrolle başlıyoruz: secret scanning. Pre-commit hook'tan GitHub push protection'a kadar katmanları kuracak, bir secret sızdığında ilk 30 dakikada neyin hangi sırayla yapılacağını Bookstore'un connection string'i üzerinden göreceğiz.