GitHub Güvenliği: Dependabot ve Code Scanning Kullanımı
Güvenlik açıklarını production’a taşımak, sysadmin’lik kariyerinde insanın yüzünü kızartan anlardan biridir. “Nasıl fark etmedik?” sorusu havada asılı kalır. GitHub’ın Dependabot ve Code Scanning özellikleri tam da bu noktada devreye giriyor ve dürüst olmak gerekirse, bu araçları ciddiye almaya başladığımdan beri baya rahat uyuyorum.
Dependabot Nedir ve Neden Önemlidir?
Projenizde kullandığınız her bağımlılık potansiyel bir güvenlik açığı kapısıdır. npm paketleri, Python pip kütüphaneleri, Maven bağımlılıkları… bunların her biri zaman içinde güvenlik açıkları barındıran versiyonlardan geçer. Dependabot, bu bağımlılıkları sürekli takip eden ve açık tespit ettiğinde sizi uyaran ya da otomatik pull request açan bir mekanizma.
GitHub, Dependabot’u üç ana modda sunar:
- Dependabot Alerts: Güvenlik açığı olan bağımlılığı tespit edip sizi uyarır
- Dependabot Security Updates: Açığı kapatan PR otomatik açılır
- Dependabot Version Updates: Güvenlik açığından bağımsız olarak bağımlılıkları güncel tutar
Fark önemli. Security updates sizi CVE’lerden korurken, version updates teknik borcu azaltmaya odaklanır.
Dependabot’u Aktif Etmek
Repo ayarlarından “Security & Analysis” sekmesine girip ilgili toggle’ları açmak işin en basit yolu. Ama ben .github/dependabot.yml dosyasıyla yönetmeyi tercih ediyorum çünkü infrastructure as code mantığıyla daha tutarlı.
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Europe/Istanbul"
open-pull-requests-limit: 10
reviewers:
- "backend-team"
labels:
- "dependencies"
- "security"
ignore:
- dependency-name: "lodash"
versions: ["4.x"]
- package-ecosystem: "pip"
directory: "/backend"
schedule:
interval: "daily"
allow:
- dependency-type: "direct"
Bu yapılandırmada birkaç kritik nokta var. open-pull-requests-limit değerini makul tutun, yoksa PR listesi dolup taşar ve ekip bunları görmezden gelmeye başlar. Tecrübelerimden: 10 ideal bir sayı. Daha fazlası kaosa davetiye çıkarıyor.
ignore bloğu da önemli. Belirli bir paketin belirli versiyonlarını atlayabilirsiniz. Legacy projede lodash 4.x sabitlemeyi düşünüyorsanız bu işe yarar, ama bu kararı bilinçli alın ve neden yaptığınızı comment olarak bırakın.
Dependabot PR’larını Otomatize Etmek
Dependabot’un açtığı PR’ları manuel review bekletmek yerine, düşük riskli güncellemeleri otomatik merge edebilirsiniz. Bunun için bir workflow yazıyoruz:
# .github/workflows/dependabot-auto-merge.yml
name: Dependabot Auto-Merge
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: write
jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Dependabot metadata al
id: metadata
uses: dependabot/fetch-metadata@v1
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Patch güncellemelerini otomatik merge et
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Minor güncellemeler için approve et
if: steps.metadata.outputs.update-type == 'version-update:semver-minor'
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Dikkat: Major güncellemeleri asla otomatik merge etmeyin. Semver’e göre major versiyonlar breaking change içerebilir ve bunu bir insan gözü görmeli. Patch ve minor güncellemeleri için otomatik merge makul bir risk kabulü.
Code Scanning: Statik Analiz Gücü
Dependabot bağımlılıklara odaklanırken, Code Scanning yazdığınız kodun kendisini analiz eder. SQL injection, XSS, hardcoded credentials, buffer overflow… bunların hepsini commit aşamasında yakalamak mümkün.
GitHub’ın varsayılan aracı CodeQL. Microsoft’un satın aldığı Semmle’dan gelen bu araç, kodu bir veritabanı gibi sorgulayan semantik analiz yapıyor. “Bu değişken kullanıcı girdisinden geliyor mu ve sanitize edilmeden SQL sorgusuna giriyor mu?” gibi sorular sorabiliyor. Bu salt syntax kontrolünden çok daha güçlü.
CodeQL Workflow Kurulumu
# .github/workflows/codeql-analysis.yml
name: "CodeQL Security Analysis"
on:
push:
branches: [ "main", "develop" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '0 2 * * 1' # Her Pazartesi gece 02:00
jobs:
analyze:
name: Analiz Et
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python' ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: CodeQL başlat
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
- name: Otomatik build
uses: github/codeql-action/autobuild@v3
- name: Analizi çalıştır
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: true
queries parametresine dikkat edin. Üç seçenek var:
- security-and-quality: Hem güvenlik hem kod kalitesi kuralları, daha geniş kapsam
- security-extended: Güvenlik odaklı ama daha agresif, false positive oranı yüksek
- security-experimental: Deneysel kurallar, production’da dikkatli kullanın
Ben çoğu projede security-extended ile başlıyorum, false positive’leri suppress ettikten sonra sistemi oturtuyorum.
Java ve Compiled Diller İçin Build Konfigürasyonu
CodeQL, compiled dillerde otomatik build mekanizmasını her zaman doğru tahmin edemez. Java veya C++ projeleri için build adımını kendiniz yazın:
- name: CodeQL başlat
uses: github/codeql-action/init@v3
with:
languages: java
- name: Java projesini build et
run: |
mvn clean compile -DskipTests
-Dmaven.repo.local=${{ github.workspace }}/.m2
--no-transfer-progress
- name: Analizi çalıştır
uses: github/codeql-action/analyze@v3
Autobuild’e güvenmek bazen saatlerce süren debug seanslarına yol açabiliyor. Özellikle kurumsal projelerde custom build scriptleri varsa, bunları açıkça belirtin.
False Positive Yönetimi
Code Scanning’in en büyük çıkmazı false positive’ler. Yeterince dikkat edilmezse ekip “wolf cried too many times” sendromuna giriyor ve gerçek uyarıları da görmezden gelmeye başlıyor.
GitHub, SARIF formatında sonuçları işler ve belirli bulguları dismissable olarak işaretlemenizi sağlar. Ama bunun bir adım ötesine geçmek için .github/codeql/codeql-config.yml dosyasını kullanabilirsiniz:
# .github/codeql/codeql-config.yml
name: "Özelleştirilmiş CodeQL Config"
queries:
- uses: security-extended
paths-ignore:
- "vendor/**"
- "node_modules/**"
- "**/*.test.js"
- "**/__mocks__/**"
- "migrations/**"
query-filters:
- exclude:
id: js/unused-local-variable
- exclude:
tags contain: experimental
paths-ignore kritik. Test dosyaları, vendor dizinleri ve migration dosyaları genellikle false positive cennetine dönüşür. Bunları dışarıda tutmak hem analiz süresini kısaltır hem de gürültüyü azaltır.
Özel CodeQL Sorguları Yazmak
İleri seviyede, organizasyonunuza özgü güvenlik kontrolleri yazabilirsiniz. Örneğin şirket içi bir kütüphanenin yanlış kullanımını tespit etmek için:
/**
* @name Şifrelenmemiş iç API çağrısı
* @description Dahili API client'ı HTTPS olmadan kullanılmamalı
* @kind problem
* @problem.severity warning
* @id custom/unencrypted-internal-api
*/
import javascript
from CallExpr call
where
call.getCalleeName() = "InternalApiClient" and
not exists(StringLiteral s |
s.getValue().matches("https://%") and
s = call.getArgument(0)
)
select call, "İç API çağrısı HTTPS kullanmıyor olabilir."
Bu sorguyu .github/codeql/queries/ dizinine koyun ve config dosyanızda referans verin. Organizasyonunuzun kodlama standartlarını otomatik denetlemenin en temiz yolu bu.
Gerçek Dünya Senaryosu: E-Ticaret Platformu
Yakın zamanda üzerinde çalıştığım bir e-ticaret projesinde şu setup’ı kurduk. Node.js backend, Python ML servisleri ve React frontend’den oluşan bir monorepo. Dependabot production’da kullandığımız express, sequelize ve jsonwebtoken paketlerini haftalık tarayacak şekilde ayarlandı.
İlk haftada Dependabot, jsonwebtoken 8.x serisinde bir CVE tespit etti. Otomatik PR açıldı, testler geçti, kıdemli developer review etti, merge ettik. Toplam süre: 45 dakika. Güvenlik açığının production’a taşınma ihtimali sıfıra indi.
Code Scanning tarafında ise daha ilginç bir şey oldu. Bir geliştiricinin yazdığı şu kodda sorun tespit edildi:
// Tehlikeli kod - CodeQL bunu yakaladı
app.get('/user/:id', async (req, res) => {
const userId = req.params.id;
// CodeQL: SQL injection riski - userId sanitize edilmemiş
const result = await db.query(`SELECT * FROM users WHERE id = ${userId}`);
res.json(result);
});
// Güvenli versiyon
app.get('/user/:id', async (req, res) => {
const userId = parseInt(req.params.id, 10);
if (isNaN(userId)) {
return res.status(400).json({ error: 'Geçersiz kullanıcı ID' });
}
const result = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
res.json(result);
});
PR review aşamasında CodeQL bu bulguyu comment olarak PR’a ekledi. Developer fark etmedi ama sistem fark etti. Bu tam olarak bu araçların yapması gereken şey.
Security Policy ve SECURITY.md
Dependabot ve Code Scanning’i kurarken bir de SECURITY.md dosyası oluşturun. Bu, güvenlik açıklarını nasıl raporlayacağınızı açıklar:
# Güvenlik Politikası
## Desteklenen Versiyonlar
- v2.x: Aktif destek
- v1.x: Yalnızca kritik güvenlik güncellemeleri
- v0.x: Destek yok
## Güvenlik Açığı Bildirme
Güvenlik açıklarını **public issue olarak açmayın**.
[email protected] adresine bildirin.
PGP anahtarı: [keybase.io/sirketiniz](https://keybase.io)
72 saat içinde yanıt vermeyi taahhüt ediyoruz.
GitHub bu dosyayı tanır ve “Report a vulnerability” butonu otomatik aktif olur. Ayrıca private vulnerability reporting özelliğini de açarsanız araştırmacılar sizi public etmeden bildirim yapabilir.
Branch Protection ile Entegrasyon
Code Scanning bulgularını branch protection rule’larına bağlamak, güvenlik açıklı kodun main’e geçmesini fiziksel olarak engeller:
Repo Ayarları > Branches > main > Branch Protection Rules yolunu izleyip “Require status checks to pass before merging” altına CodeQL workflow’unu ekleyin.
Ama dikkatli olun: Bu ayarı yaptıktan sonra CodeQL başarısız olursa hiç kimse merge yapamaz. İlk birkaç hafta querySuite: security-extended yerine daha hafif bir suite kullanıp false positive’leri temizledikten sonra kuralları sıkılaştırmak daha sağlıklı.
Sonuç
Dependabot ve Code Scanning birbirini tamamlayan iki katman oluşturuyor: biri dış bağımlılık risklerini, diğeri iç kod risklerini ele alıyor. İkisini birlikte kurmak, güvenliği bir “bir kez yap ve unut” aksiyon öğesi olmaktan çıkarıp sürekli çalışan bir süreç haline getiriyor.
Başlangıç olarak şu üç adımı öneririm: Önce Dependabot Alerts’i aktif edin ve mevcut açıkları görün. Sonra dependabot.yml ile version updates’i yapılandırın. Son olarak CodeQL workflow’unu ekleyip false positive’leri bir sprint boyunca temizleyin, ardından branch protection’a bağlayın.
Güvenlik kültürü, pahalı araçlarla değil süreçlere entegre edilmiş otomasyonla inşa edilir. GitHub bu araçları zaten size sunuyor; yapmaya çalıştığı şey sadece kullanmanız.
