OWASP LLM Top 10 2026'yı CI'ınıza Gömün
Makine-Okunur Veri Seti (JSON) ile Kapsam Karnesi
OWASP LLM Top 10 2026 sadece okunacak bir liste değil; makine-okunur bir JSON veri seti. Bu rehber, listeyi CI hattınıza, tarayıcı bulgularınıza ve kapsam karnenize nasıl gömeceğinizi somut kod örnekleriyle gösterir.
30 saniyede özet
- OWASP LLM Top 10 2026 (yayın: 4 Ağustos 2026) bir belge olmasının yanında açık bir JSON veri seti olarak da mevcut:
data/llm-top10-2026.json— GitHub ve Hugging Face üzerinde. - Her kayıt şu alanları taşır:
id,en_title,tr_title,en_summary,tr_summary,prev_2025_id,change,change_note. - Python'da tek çağrıyla yükleyin; tarayıcı/pentest bulgularınızı
LLM01:2026..LLM10:2026kanonik kimliklerine eşleyin. prev_2025_idalanı 2025→2026 yeniden eşlemesini taşır; eski referanslar (ör.LLM05:2025) çözülmeye devam eder.- CI'da iki bağımsız kapı kurun: kapsam karnesi (test paketiniz 10 kategoriye dokunuyor mu) ve bulgu kapısı (eşik üstü açık bulguda build düşer).
- Dürüstlük notu: İngilizce kimlik ve başlıklar resmî; Türkçe çeviri topluluk katkısıdır (gayriresmî). Lisans CC BY-SA 4.0.
Veri seti: alanlar, kaynak ve lisans
Amaç, listeyi kopyala-yapıştır bir tabloya sıkıştırmak değil; onu boru hattınızda sorgulanabilir bir veri kaynağına dönüştürmek. Veri seti düz bir dizi olup her öğe tek bir 2026 kategorisidir. Alanlar şunlardır:
| Alan | Tür | Açıklama |
|---|---|---|
id | string | Kanonik 2026 kimliği, ör. LLM03:2026 |
en_title | string | Resmî İngilizce başlık |
tr_title | string | Gayriresmî Türkçe başlık |
en_summary | string | Kısa İngilizce özet |
tr_summary | string | Kısa Türkçe özet |
prev_2025_id | string / null | 2025 listesindeki karşılığı (yeni giriş ise boş) |
change | string | Değişim yönü (ör. unchanged, up, down, renamed) |
change_note | string | Sıra/kapsam değişiminin kısa gerekçesi |
Dürüstlük ve lisans: İngilizce id ve en_title değerleri OWASP GenAI Security Project'in resmî 2026 belgesinden gelir ve normatif kabul edilmelidir. tr_title/tr_summary ise gayriresmî topluluk çevirisidir; yasal veya sözleşmesel metinlerde İngilizce kimliği esas alın. Veri seti CC BY-SA 4.0 ile dağıtılır: türetdiğiniz karne ve dashboard'ları da atıf vererek ve aynı lisansla (ShareAlike) paylaşmanız gerekir.
Python ile yükleme
İki yol var. GitHub'dan ham JSON çekmek, boru hattınıza sabit bir dosya bağımlılığı ekler:
import json, urllib.request
RAW = ("https://raw.githubusercontent.com/"
"fevziegeyurtsevenler/owasp-llm-top10-2026-tr/main/data/llm-top10-2026.json")
with urllib.request.urlopen(RAW) as r:
items = json.load(r)
by_id = {x["id"]: x for x in items}
for x in items:
print(x["id"], x["en_title"], "—", x["tr_title"], f"({x['change']})")
Alternatif olarak Hugging Face veri setini datasets ile yükleyebilirsiniz — versiyonlama ve cache'i onlara bırakırsınız:
from datasets import load_dataset
ds = load_dataset("fevziegeyurtsevenler/owasp-llm-top10-2026-tr", split="train")
by_id = {row["id"]: row for row in ds}
Her iki durumda da elinizde by_id sözlüğü olur; kanonik kimlikten başlığa ve özete doğrudan erişirsiniz.
2025 → 2026 yeniden eşleme (crosswalk)
2026 sürümü sıraları değiştirdi ve bir girişi (eski System Prompt Leakage) yeniden kapsamlandırdı. Eski dokümanlarınız, Jira etiketleriniz veya tarayıcı kurallarınız hâlâ 2025 kimliklerine atıfta bulunuyorsa, prev_2025_id alanı bunları kırmadan çözmenizi sağlar.
| 2026 kimliği | Başlık (TR) | 2025 karşılığı | Değişim |
|---|---|---|---|
LLM01:2026 | Komut Enjeksiyonu | LLM01:2025 | Sabit (#1) |
LLM02:2026 | Hassas Bilgi İfşası | LLM02:2025 | Sabit (#2) |
LLM03:2026 | Aşırı Yetki | LLM06:2025 | ↑ 6→3 |
LLM04:2026 | Tedarik Zinciri | LLM03:2025 | ↓ 3→4 |
LLM05:2026 | Veri ve Model Zehirlenmesi | LLM04:2025 | ↓ 4→5 |
LLM06:2026 | Sınırsız Tüketim | LLM10:2025 | ↑ 10→6 |
LLM07:2026 | Yanlış Bilgi | LLM09:2025 | ↑ 9→7 |
LLM08:2026 | Gizli Bağlam İfşası | LLM07:2025 | Yeniden kapsamlandı 7→8 |
LLM09:2026 | Vektör ve Gömme Zayıflıkları | LLM08:2025 | ↓ 8→9 |
LLM10:2026 | Hatalı Çıktı İşleme | LLM05:2025 | ↓ 5→10 |
Bu tabloyu elle taşımak yerine sözlüğü veri setinden üretin — belge güncellendikçe eşleme kendiliğinden doğru kalır:
# 2025 kimliginden 2026 kimligine cozumleme
remap = {x["prev_2025_id"]: x["id"] for x in items if x.get("prev_2025_id")}
def resolve(ref: str) -> str:
# "LLM05:2025" veya sade "LLM05" gibi eski referanslari 2026'ya tasi
key = ref if ":" in ref else f"{ref}:2025"
return remap.get(key, ref)
print(resolve("LLM05:2025")) # LLM10:2026 (Hatali Cikti Isleme)
print(resolve("LLM06:2025")) # LLM03:2026 (Asiri Yetki)
Bu detaylı gerekçeleri merak ediyorsanız 2026 değişiklik genel bakışı ve derin 2025 referansı için 2025 rehberi ayrı yazılarda ele alınıyor; bu rehber çeviriyi değil, verinin tüketimini konu alır.
Bulgularınızı kanonik kimliklere eşleyin
Tarayıcınız veya pentest raporunuz kendi iç kontrol adlarını üretir. Bunları OWASP kimliklerine bağlamak için ince bir eşleme tablosu tutun — böylece raporlarınız kategori bazında toplanabilir hâle gelir:
# Tarayici/pentest kontrol adi -> OWASP LLM 2026 kimligi
FINDING_TO_OWASP = {
"indirect_prompt_injection": "LLM01:2026",
"cross_modal_injection": "LLM01:2026", # 2026: gorsel/ses de dahil
"pii_leak": "LLM02:2026",
"tool_overreach": "LLM03:2026",
"unsigned_model_artifact": "LLM04:2026",
"rag_poisoning": "LLM05:2026",
"no_rate_limit": "LLM06:2026",
"hallucinated_fact": "LLM07:2026",
"system_prompt_leak": "LLM08:2026",
"embedding_inversion": "LLM09:2026",
"xss_from_output": "LLM10:2026",
}
def tag_finding(f: dict) -> dict:
oid = FINDING_TO_OWASP.get(f["check_id"])
f["owasp_llm_2026"] = oid
f["owasp_title"] = by_id[oid]["tr_title"] if oid else None
return f
Eşleme tablosunu tek bir dosyada tutmanın değeri, denetimde ortaya çıkar: bir bulgunun neden LLM03:2026 sayıldığını tek satırda gösterebilirsiniz. Eski raporlarda 2025 kimlikleri görürseniz, önce resolve()'dan geçirip sonra etiketleyin.
CI kapısı ve kapsam karnesi
İki farklı soruyu karıştırmayın. Kapsam karnesi, test paketinizin 10 kategorinin her birine en az bir kontrolle dokunup dokunmadığını ölçer — bu bir olgunluk göstergesidir, geçti/kaldı değil. Bulgu kapısı ise eşik üstü açık bir bulgu varsa build'i düşürür.
Önce kapsam karnesi:
import sys, json
items = json.load(open("data/llm-top10-2026.json", encoding="utf-8"))
findings = json.load(open("out/findings.json", encoding="utf-8"))
by_id = {x["id"]: x for x in items}
REQUIRED = set(by_id) # 10 kanonik kimlik
covered = {f.get("owasp_llm_2026") for f in findings} - {None}
missing = sorted(REQUIRED - covered)
coverage = 100 * (len(REQUIRED) - len(missing)) // len(REQUIRED)
print(f"Kapsam: %{coverage} Eksik: {', '.join(missing) or 'yok'}")
if coverage < 80:
sys.exit(1) # CI kapisi: esik altinda build dusur
Bu döngüyü bir GitHub Actions adımına bağlamak birkaç satır:
# .github/workflows/llm-coverage.yml
- name: OWASP LLM kapsam karnesi
run: |
python scripts/owasp_coverage.py \
--dataset data/llm-top10-2026.json \
--findings out/findings.json \
--min-coverage 80
Bir dashboard için aynı çıktıyı kategori bazında toplayın: her id için bulgu sayısı, en yüksek şiddet ve son tarama tarihi. Veri seti başlıkları ve özetleri sağladığından, panelde tr_title'ı etiket, tr_summary'yi tooltip olarak kullanabilirsiniz — kod ile içerik ayrı kalır, liste güncellenince panel de güncellenir.
Sınır: liste ne zaman yetmez
Bu liste, model uygulamanızda bir bileşen olduğunda geçerlidir. Model bir aktöre döndüğü an — çağırabileceği araçlar, oturumlar arası taşıdığı hafıza ve aşağı akışta belirlediği sonuçlarla — risk OWASP Agentic (ASI) Top 10'a kayar. İkisini birlikte kullanın; hiçbiri o zemini tek başına kapatmaz. Ajan mimarileri için Agentic/ASI Top 10 Türkçe yazısını bu veri setiyle eşleyin; ASI için de benzer bir açık veri paketi mevcuttur.
Özetle: listeyi bir PDF gibi değil, bir bağımlılık gibi ele alın. Kimlikleri kanon, çeviriyi arayüz, prev_2025_id'yi geriye uyumluluk katmanı olarak kullanın; kapsamı ölçün, bulguyu geçitleyin. Kaynak dosyalar aşağıdaki GitHub ve Hugging Face bağlantılarında; katkı ve düzeltmeler CC BY-SA 4.0 kapsamında açıktır.
Sık Sorulan Sorular
Bu veri seti resmî OWASP yayını mı?
İngilizce kimlik (id) ve başlıklar (en_title) resmî OWASP GenAI 2026 belgesinden gelir ve normatif kabul edilmelidir. Türkçe alanlar ve JSON paketleme gayriresmî topluluk katkısıdır. Lisans CC BY-SA 4.0'dır.
Eski LLM05:2025 gibi referanslarım bozulur mu?
Hayır. Veri setindeki prev_2025_id alanından bir yeniden-eşleme sözlüğü kurup eski kimlikleri 2026 karşılığına çözebilirsiniz; örneğin LLM05:2025 kaydı LLM10:2026'ya (Hatalı Çıktı İşleme) taşınır.
Kapsam karnesi ile bulgu kapısı arasındaki fark nedir?
Kapsam karnesi test paketinizin 10 kategorinin her birine en az bir kontrolle dokunup dokunmadığını ölçer (olgunluk göstergesi). Bulgu kapısı ise eşik üstü açık bir bulgu tespit edilince CI build'ini düşürür.
Ajan/agent sistemleri de bu listeyle mi kapsanıyor?
Model uygulamada bir bileşenken bu liste geçerlidir. Model araç çağıran, hafıza taşıyan bir aktöre döndüğünde risk OWASP Agentic (ASI) Top 10'a kayar. İki listeyi birlikte kullanın.
CC BY-SA 4.0 dashboard'uma ne yükler?
ShareAlike koşulu gereği, veri setinden türettiğiniz karne ve dashboard'ları da atıf vererek ve aynı CC BY-SA 4.0 lisansıyla paylaşmanız gerekir.
Veriyi nereden ve hangi dosyadan çekerim?
GitHub deposundaki data/llm-top10-2026.json dosyasından ham JSON olarak ya da Hugging Face veri seti üzerinden datasets kütüphanesiyle yükleyebilirsiniz.
Kaynaklar
| Kaynak | Link |
|---|---|
| OWASP GenAI — LLM Top 10 for 2026 (resmî belge) | genai.owasp.org |
| owasp-llm-top10-2026-tr — açık veri seti (GitHub) | github.com |
| owasp-llm-top10-2026-tr — veri seti (Hugging Face) | huggingface.co |
