Dokümanlar/API ve Webhook'lar/SARIF Entegrasyonu

SARIF Entegrasyonu

Herhangi bir kod tarama aracının (CodeQL, Semgrep, Snyk, Checkmarx, Trivy, Bandit, GitLab SAST, OWASP ZAP) SARIF çıktısını SecureCodingHub'a gönderin. Çalıştırmadaki her benzersiz CWE, commit yazarının hesabında bir atamaya dönüşür — genellikle merge'den saniyeler sonra.

CI neden doğru tetikleyicidir

Genel "her geliştirici aynı OWASP Top 10 kursunu alır" tarzı yayılımların tamamlanma oranı düşük, kalıcılığı daha da düşüktür. CI entegrasyonu modeli tersine çevirir: eğitim özellikle sorunu çıkaran geliştiriciye, özellikle ihtiyaç duyduğu zafiyet sınıfında ve onu açığa çıkaran merge'e bağlı 14 günlük bir teslim tarihiyle atanır. Denetçilerin tam zamanında güvenli kodlama eğitimi dediği şey budur.

Uçtan uca nasıl çalışır

1

SAST aracınız bir CI işinin parçası olarak SARIF 2.1.0 dosyası üretir.

2

Bir CI adımı, commit meta verisini request header'ları olarak taşıyarak dosyayı /api/public/v1/sarif adresine POST eder.

3

SecureCodingHub her result'i ayrıştırır, CWE etiketlerini çıkarır ve her birini dahili CWE-konu haritamızda arar.

4

Eşlenen her benzersiz konu için, e-postası X-Commit-Author-Email ile eşleşen kullanıcı üzerinde 14 günlük teslim tarihiyle bir atama oluşturulur.

5

Senkron yanıtın döndüğü payload ile bir sarif.ingested webhook'u tetiklenir.

Uç nokta

POST /api/public/v1/sarif
Authorization: Bearer scs_live_…
Content-Type: application/json
X-Source: github-codeql
X-Repo: acme/payments-api
X-Branch: main
X-Commit-Sha: 9c2f4b8e0c1d…
X-Commit-Author-Email: jane.smith@acme.com

<SARIF 2.1.0 JSON body, up to 10 MB>

Gerekli kapsam: sarif:ingest.

İstek header'ları

HeaderZorunluAnlam
X-SourceSerbest formatlı araç tanımlayıcı — örn. github-codeql, snyk, semgrep-ci. Denetim için kaydedilir.
X-RepoRepo slug'ı (owner/name). Denetim için kaydedilir.
X-BranchBranch adı. Denetim için kaydedilir.
X-Commit-ShaönerilenCommit hash'i. 24 saatlik idempotency için X-Repo ile birlikte kullanılır.
X-Commit-Author-EmailönerilenCommit yazarının e-postası. Bir SecureCodingHub kullanıcısına çözülür; atamalar ona iliştirilir. E-posta bir kullanıcıyla eşleşmezse çalıştırma yine içeri alınır ama atama oluşturulmaz.

Yanıt

{
  "ingestionId": "7e4c9d09-86ca-4125-bbd8-7fae54c8f654",
  "findingsCount": 2,
  "uniqueCwes": ["CWE-79", "CWE-89"],
  "unmappedCwes": [],
  "assignmentsCreated": 12,
  "notes": []
}
  • findingsCount — ayrıştırılan toplam result girdisi sayısı.
  • uniqueCwes — tüm bulgular boyunca anılan CWE kümesi.
  • unmappedCwes — konuya eşleyemediğimiz CWE'ler. Kapsam genişletmesi istiyorsanız destek'e gönderin.
  • assignmentsCreated — yeni atama kayıtlarının sayısı (mevcut tekrarlar atlanır).
  • notes — kritik olmayan uyarılar (örn. geçersiz commit yazarı e-posta formatı).

Idempotency

Aynı SARIF dosyasını tekrar içeri almak güvenlidir. (organization, repo, commit_sha) kümesi idempotency anahtarıdır — 24 saatlik bir pencere içinde gelen tekrar, orijinal ingestionId ve assignmentsCreated: 0 ile 200 döner. Bu, aynı commit üzerinde tekrar çalışan CI iş akışlarının (rebase, manuel yeniden çalıştırma, PR'a push) tekrarlı atamalar üretmemesi anlamına gelir.

GitHub Actions örneği

CodeQL veya Semgrep işiniz results.sarif ürettikten sonra şu adımı bir iş akışına koyun:

- name: Send SARIF to SecureCodingHub
  if: always()
  run: |
    curl -sS -f -X POST \
      -H "Authorization: Bearer $SCH_API_KEY" \
      -H "Content-Type: application/json" \
      -H "X-Source: github-codeql" \
      -H "X-Repo: ${{ github.repository }}" \
      -H "X-Branch: ${{ github.ref_name }}" \
      -H "X-Commit-Sha: ${{ github.sha }}" \
      -H "X-Commit-Author-Email: ${{ github.event.head_commit.author.email }}" \
      --data-binary @results.sarif \
      https://api.limeplate.com/api/public/v1/sarif
  env:
    SCH_API_KEY: ${{ secrets.SCH_API_KEY }}

Anahtarı repo veya kurum secrets'ına saklayın. if: always() guard'ı, güvenlik işi build'i başarısız işaretlemiş olsa bile bulguların gönderilmesini sağlar — eğitim atamalarının tetiklenmesini en çok istediğiniz an budur.

GitLab CI örneği

send_sarif_to_sch:
  stage: post-security
  image: curlimages/curl:latest
  needs: ["sast"]
  script:
    - >
      curl -sS -f -X POST
      -H "Authorization: Bearer $SCH_API_KEY"
      -H "Content-Type: application/json"
      -H "X-Source: gitlab-sast"
      -H "X-Repo: $CI_PROJECT_PATH"
      -H "X-Branch: $CI_COMMIT_BRANCH"
      -H "X-Commit-Sha: $CI_COMMIT_SHA"
      -H "X-Commit-Author-Email: $GITLAB_USER_EMAIL"
      --data-binary @gl-sast-report.json
      https://api.limeplate.com/api/public/v1/sarif
  rules:
    - if: $CI_COMMIT_BRANCH

GitLab SAST raporu SARIF uyumludur — dönüşüme gerek yoktur.

Semgrep örneği

semgrep ci --sarif --output results.sarif
curl -sS -f -X POST \
  -H "Authorization: Bearer $SCH_API_KEY" \
  -H "X-Source: semgrep" \
  -H "X-Repo: $REPO" \
  -H "X-Commit-Sha: $COMMIT" \
  -H "X-Commit-Author-Email: $AUTHOR_EMAIL" \
  --data-binary @results.sarif \
  https://api.limeplate.com/api/public/v1/sarif

CWE kapsamı

SecureCodingHub şu anda OWASP Top 10, OWASP API Security Top 10, OWASP Mobile Top 10 ve CWE Top 25'i eğitim konularına eşler. Bu set dışındaki CWE ID'leriyle etiketlenen bulgular yanıtın unmappedCwes listesinde görünür. SARIF tag tarafında kabul ettiğimiz yaygın formatlar:

  • external/cwe/cwe-89 (CodeQL standardı)
  • cwe-89
  • CWE-89
  • cwe:89

Tag'ler hem result.properties.tags hem de buna karşılık gelen tool.driver.rules[].properties.tags'den okunur.

Gövde boyutu üst sınırı

SARIF uç noktası sıkıştırılmamış olarak 10 MB'a kadar payload kabul eder. Tek bir repo için gerçek dünyadaki SAST raporlarının çoğu bu sınırın çok altındadır. Bu sınırı aşan kurumsal ölçekte bir monorepo raporunuz varsa, tool driver başına bölün (driver başına bir SARIF çalıştırması) ve her parçayı POST edin — aynı commit SHA altında idempotent olacaklardır.

Başarısızlık modları

BelirtiOlası neden
assignmentsCreated: 0 ile 200Commit yazarının e-postası kurumunuzda kullanıcı değil ya da tüm CWE'ler zaten atanmış.
unmappedCwes boş değil iken 200Bulgular henüz eğitim konusu olmayan CWE'lere referans veriyor. Listeyi destek ekibine iletin.
400 empty_bodyCurl'de --data-binary @file.sarif eksikti.
413 body_too_largeSARIF 10 MB'ı aşıyor. Driver'a göre bölün.
idempotency: ile başlayan bir notes girdisi içeren 200Aynı (repo, commit) 24 saat içinde zaten içeri alınmış. Yanıt diğer açılardan assignmentsCreated: 0 ile yeni bir içeri alımdan ayırt edilemez — yok sayılabilir.