
SaaS Güvenlik Kontrol Listesi: Yayından Önce Çalıştırdığımız 40 Kontrol (2026)
Bir SaaS güvenlik kontrol listesi, henüz sahip olmadığınız bir yığın uyumluluk rozetinden daha değerlidir. Rahatsız edici gerçek şu: çoğu yayın kontrol listesi neyi güvence altına almanız gerektiğini söyler, nasıl yapacağınızı hiç göstermez. Bu liste kodu da verir. Biz Next.js ve Supabase üzerine inşa ediyoruz; eksik tek bir tenant_id filtresinin bir test hesabına başka bir müşterinin verisini okutturduğunu gördük ve IBM'in 2024 Veri İhlali Maliyeti Raporu küresel ortalamayı $4.88M olarak belirledi. Yayına çıkmak için SOC 2'ye ihtiyacınız yok. Aşağıdaki, gruplanmış, çalıştırılabilir ve OWASP ile NIST'e eşlenmiş uygulama katmanı temeline ihtiyacınız var.
Öne Çıkan Noktalar
- Yayına çıkmak için SOC 2'ye ya da pentest'e ihtiyacınız yok. Aşağıdaki uygulama katmanı temeline ihtiyacınız var.
- En tehlikeli yayın hatası, eksik bir
tenant_idkontrolünden kaynaklanan tenant'lar arası veri sızıntısıdır. - Kendi auth'unuzu asla sıfırdan kurmayın. Auth.js, Clerk veya Supabase Auth kullanın.
- Dağıtım yapmadan önce
NEXT_PUBLIC_ön eklerini denetleyin. Bir secret'ı sızdırmanın en hızlı yolu bu.
Bu temel, OWASP ASVS 5.0 ile NIST Güvenli Yazılım Geliştirme Çerçevesi (SSDF)'ye eşlenir; Google'ın bu konuda en çok güvendiği iki kaynak ve dikkat çekici biçimde, en üst sıradaki rehberlerin hiçbirinin zahmet edip atıfta bulunmadığı iki kaynak.
Yayın Öncesi Güvenlik Kontrol Listeniz (Hızlı Sürüm)
Bunlar, yayına çıkmadan önce karşılamanız gereken asgari güvenlik gereksinimleridir; altı kategoriye ayrılmıştır. Kırk madde. Yukarıdan aşağıya çalıştırın, kod bölümlerini geliştiricinize verin ve aşağıdaki öncelik tablosunda P0 olarak işaretlenen her şeyi yayın engelleyici olarak ele alın.
Secrets ve Yapılandırma
.env, ilk commit'ten itibaren.gitignoreiçinde ve hiç commit edilmedi.- Her
NEXT_PUBLIC_veVITE_ön eki denetlendi; hiçbir gizli bilgi tarayıcıya gitmiyor. - Sunucu secret'ları repo'da değil bir yöneticide (platform env değişkenleri, AWS Secrets Manager, Vault) tutuluyor.
- Git geçmişine bir kez bile değmiş her anahtar, yayından önce döndürüldü.
- Loglarda, hata yanıtlarında veya istemci paketinde hiçbir secret görünmüyor.
- Derlenen paketi canlı anahtarlar için grep'lediniz (
grep -r "sk_live" .next/).
Auth ve Erişim
- Auth, sıfırdan yazılmadı; bir kütüphane (Auth.js, Clerk veya Supabase Auth) üzerine kuruldu.
- Hesaplarda MFA (çok faktörlü kimlik doğrulama) mevcut.
- Oturum çerezleri
Secure,HttpOnlyveSameSiteayarlarını taşıyor. - Hiçbir JWT ya da oturum token'ı
localStorage'da saklanmıyor. - RBAC ve en az ayrıcalık ilkesine dayalı roller yalnızca arayüzde gizlenmiyor, sunucu tarafında uygulanıyor.
- Şifreler Argon2 veya bcrypt ile hash'leniyor (yalnızca auth'u kendiniz yönetiyorsanız geçerli).
- Şifre sıfırlama ve e-posta doğrulama akışları kötüye kullanıma karşı test edildi.
Veri ve Tenant Yönetimi
- Her sorgu bir
tenant_idfiltresi taşıyor. - Tenant kapsamlaması her sorguda hatırlanmıyor; ORM ya da repository katmanında zorunlu kılınıyor.
- Satır düzeyinde güvenlik (RLS) etkin ve başarısızlık senaryoları biliniyor.
- Her nesne-ID endpoint'inde bir sahiplik kontrolü çalışıyor (bu IDOR'u ortadan kaldırır).
tenant_id, önbellek anahtarlarına ve nesne depolama yollarına dahil ediliyor.- Veriler hem bekleme hâlinde hem de aktarım sırasında şifreleniyor.
- Ödeme ve webhook imzaları (Stripe vb.) sunucu tarafında doğrulanıyor.
Bağımlılıklar ve Tedarik Zinciri
npm auditveyapnpm audit, yüksek ve kritik bulgulardan temiz (ya da açıkça triyaj edilmiş).- Dependabot veya Renovate etkinleştirildi.
- Snyk veya Socket, daha derin SCA'nın yanı sıra kötü amaçlı yazılım ve lisans kontrollerini çalıştırıyor.
- Kilit dosyası (lockfile) commit edildi.
- Kritik yol üzerinde terk edilmiş veya bakımsız hiçbir paket yok.
- Docker kullanıyorsanız container imajları taranıyor.
Ağ ve Aktarım
- HTTPS her yerde HSTS preload ile zorunlu kılınıyor.
- Bir Content-Security-Policy ayarlandı (önce report-only, sonra zorunlu).
X-Content-Type-Options: nosniffveX-Frame-Options/frame-ancestorsayarlandı.Referrer-PolicyvePermissions-Policyayarlandı.- CORS bir izin listesi kullanıyor; credentials ile asla
*kullanılmıyor. - Hız sınırlama, auth ve maliyetli endpoint'leri koruyor.
- Her endpoint, girdiyi bir şema ile doğruluyor (Zod veya benzeri).
İzleme ve Müdahale
- Merkezi denetim günlükleri kimin neye ne zaman eriştiğini kaydediyor.
- Hata yönetimi kullanıcılara asla stack trace sızdırmıyor.
- Auth anormalliklerinde (başarısız giriş sıçramaları, imkânsız seyahat) uyarılar tetikleniyor.
- Otomatik yedeklemeler çalışıyor ve bir geri yükleme testi yapıldı.
- Bir olay müdahale kişisi ve tek sayfalık bir runbook mevcut.
- Çalışma süresi ve hata izleme (Sentry veya benzeri) devrede.
- Bir pentest'e ne zaman başvuracağınızı biliyorsunuz.
Önce Düzeltilecekler: Öncelik Sırası
Her madde yayını engellemez. Bu triyaj tablosu, temeli "atlanırsa verdiği zarara" göre sıralar; böylece bir kurucu neyin pazarlık konusu olmadığını bilir. P0 = yayından önce düzelt, P1 = ilk hafta düzelt, P2 = çeyrek içinde düzelt.
| Kontrol | Kategori | Atlarsanız | Düzeltme çabası | Yayın engelleyici mi? |
|---|---|---|---|---|
| Her sorguda tenant'lar arası izolasyon | Veri ve Tenant Yönetimi | Bir müşteri başkasının verisini okur | Orta | P0: yayını engeller |
| Secret'lar istemci paketinin dışında | Secrets ve Yapılandırma | Herkese açık API anahtarları, hesap ele geçirme | Düşük | P0: yayını engeller |
| Nesne-ID endpoint'lerinde sahiplik kontrolü | Veri ve Tenant Yönetimi | IDOR: bir id'yi artırmak kayıtları sızdırır | Düşük | P0: yayını engeller |
| Auth bir kütüphane üzerinde, sıfırdan değil | Auth ve Erişim | Yayınlanmış auth hataları, bozuk oturumlar | Orta | P0: yayını engeller |
| Her yerde HTTPS ve HSTS | Ağ ve Aktarım | Hat üzerinden token hırsızlığı | Düşük | P0: yayını engeller |
| npm audit yüksek/kritik bulgulardan temiz | Bağımlılıklar | Geçişli bir bağımlılıkta bilinen CVE | Düşük | P1: ilk hafta |
| Auth endpoint'lerinde hız sınırlama | Ağ ve Aktarım | Kimlik bilgisi doldurma, brute force | Düşük | P1: ilk hafta |
| Güvenlik header'ları (CSP, HSTS, nosniff) | Ağ ve Aktarım | XSS, clickjacking, MIME saldırıları | Düşük | P1: ilk hafta |
| Merkezi denetim günlükleri | İzleme | Bir ihlali göremez ya da kanıtlayamazsınız | Orta | P1: ilk hafta |
| Test edilmiş yedek geri yükleme | İzleme | Geri yüklenemeyen bir yedek hiçbir şey değildir | Orta | P1: ilk hafta |
| Hesaplarda MFA mevcut | Auth ve Erişim | Daha kolay hesap ele geçirme | Düşük | P2: bu çeyrek |
| Report-only'nin ötesinde tam CSP zorunlu | Ağ ve Aktarım | Kalan XSS yüzeyi | Orta | P2: bu çeyrek |
Secrets ve Yapılandırma: İstemci Paketinize Sızan Bir Anahtar Var mı?
Yayında secret hijyeni, hiçbir kimlik bilgisinin tarayıcıya ulaşmaması demektir. Next.js'teki NEXT_PUBLIC_ ön eki (ve Vite'daki VITE_) değeri her ziyaretçiye gönderir; bu yüzden tek bir yanlış ön ek bir anahtarı sızdırır. .env'i git'in dışında tutun, sunucu secret'larını bir yöneticiye koyun ve dağıtımdan önce derleme çıktınızı grep'leyin.
En sık gördüğümüz tuzak şu: NEXT_PUBLIC_ "herkese açık bilgi" anlamına gelmez. "Bunu kelimenin tam anlamıyla her ziyaretçinin tarayıcısına gönderiyorum" anlamına gelir. Bir Stripe secret'ını ya da bir service-role anahtarını bu şekilde önekleyin; DevTools'u açan herkes için pakette canlı hâle gelir.
# .env.local (hata)
NEXT_PUBLIC_STRIPE_SECRET=sk_live_51H... # KÖTÜ: her tarayıcıya gider
STRIPE_SECRET_KEY=sk_live_51H... # İYİ: yalnızca sunucu
# Herkese açık (paylaşılması güvenli) vs yalnızca sunucu
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... # anon anahtarın herkese açık olması amaçlanmıştır
SUPABASE_SERVICE_ROLE_KEY=eyJ... # buna asla NEXT_PUBLIC_ eklemeyin
# Dağıtmadan önce sızmış bir anahtarı yakalayın
grep -r "sk_live" .next/ # herhangi bir eşleşme, istemci paketinizde bir secret olduğu anlamına gelirSecret temelinin geri kalanı sıkıcı ve pazarlık konusu değil: ilk commit'ten itibaren .gitignore içinde .env, repo yerine bir yöneticide sunucu secret'ları ve git geçmişine bir kez bile değmiş her anahtarın döndürülmesi (bir commit'i silmek onu sızdırılmamış hâle getirmez). Sızmış bir dağıtım token'ı, tam olarak Vercel olayı gibi ihlallerin başladığı yerdir; bu yüzden her token'ı sanki birinin izleme listesindeymiş gibi ele alın.
Auth ve Erişim: Kendi Auth'unuzu mu Kurmalısınız, Kütüphane mi Kullanmalısınız?
Kendi auth'unuzu mu kurmalısınız yoksa bir kütüphane mi kullanmalısınız? Neredeyse her zaman bir kütüphane kullanın. Auth.js, Clerk ve Supabase Auth, aksi hâlde üretimde yeniden keşfedeceğiniz yılların uç durumlarını (oturum sabitleme, token iptali, sıfırlama akışı kötüye kullanımı) zaten çözmüş durumda. Kendi başınıza kurmak, yalnızca bir güvenlik mühendisiniz ve hiçbir sağlayıcının uymadığı bir nedeniniz varsa savunulabilir; bu da nadirdir.
Kendi auth'unuzu sıfırdan kurmak, ayda $25 tasarruf etmenin en pahalı yoludur. İşte dürüst seçeneklerin karşılaştırması.
| Seçenek | En uygun olduğu durum | Yerleşik MFA | Varsayılan oturum | Tuzak |
|---|---|---|---|---|
| Auth.js (NextAuth) | Ücretsiz, kendi barındırdığınız, tam kontrol istiyorsanız | Sağlayıcılar/eklentiler üzerinden | JWT veya veritabanı | Her güvenlik uç durumunun sorumluluğu sizde |
| Clerk | Kutudan çıktığı gibi MFA, arayüz ve organizasyon istiyorsanız | Evet | Yönetilen | Ücretli katmanlar aktif kullanıcı sayısıyla ölçeklenir |
| Supabase Auth | Zaten Supabase ve Postgres RLS kullanıyorsanız | Evet | JWT | RLS politikasının kalitesi size bağlı |
| Sıfırdan kurun | Bir güvenlik mühendisiniz ve hiçbir sağlayıcı uymuyorsa | Siz kurarsınız | Siz kurarsınız | Çoğu auth hatası tam burada başlar |
Bir kütüphane seçip yapılandırmayı atlayan ekipleri batıran iki tuzak var. Birincisi, JWT iptali gerçekten zor; bu yüzden çalınan bir token süresi dolana kadar geçerli kalır. Token ömürlerini kısa tutun ve hassas her şey için sunucu taraflı oturumları tercih edin. İkincisi, localStorage'daki token'lar herhangi bir XSS payload'ı tarafından çalınabilir; bu yüzden oturumları Secure ve SameSite ile httpOnly çerezlerde saklayın. RBAC'ı arayüzde düğmeleri gizleyerek değil, sunucuda uygulayın.
SaaS'ınız bir yapay zeka ya da LLM özelliği sunuyorsa, model girdisini de güvenilmeyen bir auth sınırı olarak ele alın. Prompt injection'ı önleme rehberimize bakın; çünkü araç erişimi olan jailbreak edilmiş bir asistan, sohbet penceresi giymiş bir erişim kontrolü sorunudur.
Veri ve Tenant Yönetimi: Bir Tenant'ın Diğerinin Verisini Okumasını Nasıl Engellersiniz?
Tenant izolasyonu, her sorgunun, önbellek anahtarının ve depolama yolunun mevcut tenant'a kapsamlandığı anlamına gelir. Eksik bir tenant_id filtresi, bir müşterinin başka birinin verisini okumasına izin verir; bu, var olan en tehlikeli yayın hatasıdır. Satır düzeyinde güvenlik (RLS) yardımcı olur ama bir emniyet kemeridir, güç alanı değil; bu yüzden her nesne-ID endpoint'ine de sahiplik kontrolleri ekleyin.
Bu, hiçbir rakibin kod olarak ele almadığı bölüm ve tenant'lar arası sızıntıların üretime sızmasının nedeni tam olarak bu. Düzeltme, bir ID'ye tek başına asla güvenmemekle başlar. Her okumayı çağıranın tenant'ına kapsamlayın ve bunu veri katmanında zorunlu kılın ki kimse her sorguda bunu hatırlamak zorunda kalmasın.
// KÖTÜ: tenant kapsamı yok. Geçerli her id, herhangi bir tenant'ın satırını döndürür.
const order = await db.order.findFirst({ where: { id } });
// İYİ: her okumada çağıranın tenant'ına kapsamlanmış.
const order = await db.order.findFirst({
where: { id, tenantId: session.tenantId },
});İlgili hata IDOR'dur (güvensiz doğrudan nesne referansı); OWASP API Security Top 10 listesi bunu API1: Broken Object Level Authorization başlığı altına koyar. Bir test hesabı URL'deki bir ID'yi artırır ve asla görmemesi gereken bir kaydı okur. PortSwigger'ın Web Security Academy'si, saldırganların bunları nasıl bulduğuna dair tam bir anlatım sunuyor. Düzeltme tek bir sahiplik kontrolüdür.
// GET /api/invoices/1234, bir test hesabı id'yi artırır
// ve başka bir tenant'ın faturasını okur. Klasik BOLA.
const invoice = await db.invoice.findUnique({ where: { id } });
// Düzeltme: herhangi bir şey döndürmeden önce sahipliği doğrulayın.
if (invoice.tenantId !== session.tenantId) {
return res.status(403).json({ error: "Forbidden" });
}Sizi dürüst tutan çerçeve şu: her IDOR bir tenant izolasyonu hatasıdır ama her tenant izolasyonu hatası bir IDOR değildir. Postgres satır düzeyinde güvenliği bunların çoğunu veritabanında yakalar ama ona güvenmeden önce bilmeye değer sessiz başarısızlık senaryoları vardır.
-- Postgres RLS: bir emniyet kemeri, güç alanı değil.
alter table orders enable row level security;
create policy tenant_isolation on orders
using (tenant_id = current_setting('app.tenant_id')::uuid);
-- Sessiz başarısızlık tuzağı: havuzlanmış bir bağlantıda app.tenant_id'yi
-- SET etmeyi unutun; politika ÖNCEKİ isteğin tenant'ını okur.Bağlantı havuzu kirlenmesi, async-context sızıntıları ve paylaşılan önbellek zehirlenmesi hepsi RLS'yi sessizce alt eder; bu yüzden OWASP Multi-Tenant Security Cheat Sheet, önbellek anahtarlarını ve depolama yollarını da tenant ile öneklemenizi söyler. OWASP ASVS 5.0'un erişim kontrolü bölümü ve Supabase RLS dokümantasyonu, burada baştan sona okunmaya değer iki kaynaktır.
Bağımlılıklar ve Tedarik Zinciri: node_modules İçinde Neler Saklanıyor?
Uygulamanız yalnızca en zayıf geçişli bağımlılığı kadar güvenlidir. CI'da npm audit veya pnpm audit çalıştırın ve yayından önce yüksek ya da kritik bulgularda derlemeyi başarısız kılın. Otomatik güncellemeler için Dependabot veya Renovate, daha derin kötü amaçlı yazılım ve lisans kontrolleri için Snyk veya Socket ekleyin.
Tuzak, denetimi bir kez elle çalıştırıp yeşili görmek ve bir daha hiç çalıştırmamaktır. Bunu CI'a bağlayın ki dokunmadığınız bir pakette yeni bir CVE bile merge'i engellesin.
# .github/workflows/ci.yml: yüksek/kritik bulguda merge'i engelle
- name: Audit dependencies
run: npm audit --audit-level=high # sıfır olmayan çıkış kodu job'ı başarısız kılarnpm audit dokümantasyonu, önem seviyelerini ve yalnızca dev bulgularını yok saymak isterseniz --production bayrağını ele alır. Ancak otomatik tarama asgari koşuldur; bir bağımlılık tarayıcısının kaçırdığı kod kokularını ve enjeksiyon yollarını yakalayan daha derin statik analiz için SonarQube değerlendirmemize bakın. Kilit dosyanızı commit edin, yıllardır sürüm yayınlamamış paketleri bırakın ve Docker kullanıyorsanız container imajınızı tarayın.
Ağ ve Aktarım: Bir SaaS Gerçekte Hangi Güvenlik Header'lere İhtiyaç Duyar?
Bir SaaS hangi güvenlik header'lere ihtiyaç duyar? HTTPS artı HSTS ve kısa bir header seti, istismarı en kolay boşlukları kapatır. Bir Content-Security-Policy, joker karakter yerine bir CORS izin listesi ve auth ile maliyetli endpoint'lerde hız sınırları ekleyin. Kötü payload'ların iş mantığınıza asla ulaşmaması için her girdiyi Zod gibi bir şema ile doğrulayın.
Bugüne kadar icat edilmiş her header'a ihtiyacınız yok. Bu kısa listeye ihtiyacınız var ve MDN güvenlik-header'ları referansı her birini derinlemesine açıklıyor.
| Header | Önerilen değer | Neyi engeller |
|---|---|---|
| Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | Protokol düşürme, SSL-strip saldırıları |
| Content-Security-Policy | default-src 'self'; report-only ile başlayın | XSS, enjekte edilmiş scriptler, veri sızdırma |
| X-Content-Type-Options | nosniff | Bir yüklemeyi script'e dönüştüren MIME-sniffing |
| X-Frame-Options / frame-ancestors | DENY (veya frame-ancestors 'none') | Gizli iframe'ler üzerinden clickjacking |
| Referrer-Policy | strict-origin-when-cross-origin | Tam URL'lerin (ve içindeki token'ların) sızması |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | Cihaz API'lerine dokunan kötü niyetli scriptler |
Header'ları edge'de bir kez ayarlayın ve bir script'in giriş rotanızı bütün gece brute-force edememesi için bir hız sınırlayıcı ekleyin.
// next.config.js: her yanıtta güvenlik header'ları
const securityHeaders = [
{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
];
// Auth rotalarını hız sınırlayın (Upstash örneği)
const { success } = await ratelimit.limit(ip);
if (!success) return new Response("Too many requests", { status: 429 });Kendi uygulamanızı bozmamak için CSP'nizi report-only ile başlatın, birkaç gün ihlal raporlarını izleyin, sonra zorunlu moda geçirin. CORS'u adlandırılmış bir izin listesiyle sınırlayın ve *'ı asla credentials ile eşleştirmeyin.
İzleme ve Müdahale: İhlale Uğradığınızı Nasıl Anlarsınız?
Göremediğiniz bir şeye müdahale edemezsiniz. Yayından önce merkezi denetim günlükleri, başarısız giriş sıçramaları gibi auth anormalliklerinde uyarılar, test edilmiş geri yüklemesi olan otomatik yedeklemeler ve tek sayfalık bir olay runbook'u kurun. Test edilmemiş bir yedek bir umuttur, yedek değil; runbook'u yazma zamanı şimdi, bir olayın ortasında değil.
IBM verileri, bir ihlali tespit edip kapsam altına almanın ortalama süresini 258 gün olarak veriyor; ve günlükleriniz kimin neye dokunduğunu kaydetmiyorsa bu sayıyı küçültemezsiniz. Onları merkezileştirin, önemli anormalliklerde (başarısız giriş sıçramaları, imkânsız seyahat girişleri, ani dışa aktarım hacmi) uyarın ve hata işleyicinizin, iç yapınızı ifşa eden bir stack trace yerine temiz bir mesaj döndürdüğünden emin olun.
Modern ihlal tespiti, statik kurallardan çok anomali izlemeye dayanır; bunun gerçekte nasıl çalıştığı hakkında daha fazlasını yapay zekanın veri ihlallerini nasıl önlediği yazımızda bulabilirsiniz. Çerçeve desteği için NIST SSDF (SP 800-218), müdahale-ve-izleme pratiklerini sade bir dille ortaya koyar. Bir geri yüklemeyi veritabanınız kaybolduktan sonra değil, yayından önce test edin.
Kendi Yayınlarımızı İncelerken Gerçekte Ne Buluyoruz?
Ekibimiz bir derleme üzerinde yayın öncesi güvenlik geçişi yaptığında, kendi ürünümüz olsun ya da bir müşterininki olsun, iki eksik her şeyden daha sık ortaya çıkıyor. Birincisi: bir NEXT_PUBLIC_ ön eki üzerinden tarayıcıya binen bir secret, genellikle birinin istemci taraflı bir çağrıyı çalıştırmak için önekleyerek eklediği üçüncü taraf bir API anahtarı. İkincisi: en az bir endpoint'in tenant_id kapsamının ya da sahiplik kontrolünün eksik olması.
Tenant kapsamı eksikliği korkutucu olandır çünkü uygulama gayet iyi görünür. Her sayfa yükleniyor. Hata yalnızca biri URL'deki bir ID'yi değiştirdiğinde ortaya çıkar. Bir incelemede, GET /api/orders/:id giriş yapmış herhangi bir kullanıcıya herhangi bir siparişi döndürüyordu; bir test hesabı, sayıyı artırarak başka bir tenant'ın siparişlerini okudu. Düzeltme iki satırdı: döndürmeden önce order.tenantId'yi session.tenantId ile karşılaştırmak.
Burada size uydurma bir yakalama oranı söylemeyeceğiz. Dürüst ve tekrarlanabilir olan şu: NEXT_PUBLIC_ sızıntısı ve eksik tenant kapsamı, neredeyse her ilk-geçiş incelemede bulduğumuz iki şey ve ikisi de nereye bakacağınızı bildiğinizde düzeltmesi ucuz. Kontrol listesinin bunları P0 olarak en öne koymasının nedeni tam olarak bu.
Bu geçişi yayın gününden önce sizin için bir ekibin yapmasını tercih ederseniz, yaptığımız iş tam olarak bu. Yayın öncesi güvenlik incelemesi alın →
Yazar Hakkında
Mert Batur, Techsy.io'nun Kurucu Ortağı. Ekip, B2B müşteriler için yapay zeka ajanları, otomasyon sistemleri ve sesli/SDR hatları geliştiriyor. Mert, Techsy ekibinin üretimde fiilen kullandığı LLM araç yığını hakkında yazıyor. LinkedIn üzerinden bağlantı kurabilirsiniz.
Sıkça Sorulan Sorular
Bir SaaS güvenlik kontrol listesinde neler olmalı?
Altı kategori: secrets ve yapılandırma (anahtarları istemci paketinin dışında tutun), auth ve erişim (bir kütüphane kullanın, MFA ekleyin), veri ve tenant yönetimi (tenant_id kapsamlaması artı sahiplik kontrolleri), bağımlılıklar (CI'da npm audit), ağ ve aktarım (HTTPS, HSTS, CSP, hız sınırları) ve izleme ile müdahale (denetim günlükleri, test edilmiş yedekler, bir runbook).
SaaS'ım yayına çıkacak kadar güvenli mi?
P0 temeli tamamlandığında hazırsınız demektir: secret'lar istemci paketinin dışında, her sorguda tenant izolasyonu, bir kütüphane üzerinde auth, güvenlik header'larıyla HTTPS ve temiz bir bağımlılık taraması. Mükemmellik burada ölçüt değil. Temeli karşılayan, yayınlanmış ve izlenen bir uygulama, hiç yayınlanmayan "mükemmel" bir uygulamayı her zaman geçer.
Bir SaaS'ı yayınlamadan önce sızma testine ihtiyacım var mı?
Yasal olarak yayınlamak için gerekmez. Ödeme veya kişisel veri işliyorsanız, kurumsal alıcıları hedefliyorsanız ya da bir denetçi veya yatırımcı istiyorsa önceliklendirin. MVP aşamasında o çabayı önce uygulama katmanı temeline ve OWASP Top 10'a harcayın. Bariz IDOR ve header boşlukları zaten kapatıldığında bir pentest daha fazlasını bulur.
Bir SaaS'ı yayınlamak için SOC 2'ye ihtiyacım var mı?
Hayır. Geçen hafta yayınlanmış bir startup'tan hiçbir müşteri SOC 2 beklemez. Bu bir yayın kapısı değil, kurumsal satış anahtarıdır ve aylar sürer. Uygulama katmanı temeliyle yayınlayın, sonra gerçek bir kurumsal anlaşma bunu gerektirdiğinde, öncesinde değil, SOC 2 sürecine başlayın.
Kendi kimlik doğrulamamı mı kurmalıyım yoksa Auth.js, Clerk ya da Supabase Auth gibi bir kütüphane mi kullanmalıyım?
Neredeyse her zaman bir kütüphane kullanın. Auth.js, Clerk ve Supabase Auth, çoğu kendin-yap auth hatasına neden olan oturum, token ve sıfırlama akışı uç durumlarını zaten çözdü. Kendi başınıza kurmak yalnızca bir güvenlik mühendisiniz ve hiçbir sağlayıcının karşılamadığı katı bir gereksiniminiz varsa savunulabilir; bu da gerçekten nadirdir.
Secret'ları istemci paketimin dışında nasıl tutarım?
Her NEXT_PUBLIC_ ve VITE_ ön ekini denetleyin; çünkü bu ön eki taşıyan her şey tarayıcıya gider. .env'i ilk commit'ten itibaren git'in dışında tutun, sunucu secret'larını bir yöneticide saklayın ve sızmış bir anahtarı yakalamak için dağıtımdan önce derlenen paketinizi grep'leyin (grep -r "sk_live" .next/).
Çok tenant'lı bir SaaS'ta tenant verisini nasıl izole ederim?
Her sorguya bir tenant_id filtresi koyun ve bunu otomatik olması için ORM ya da repository katmanında zorunlu kılın. Satır düzeyinde güvenliği etkinleştirin ve başarısızlık senaryolarını (havuz kirlenmesi, async sızıntıları) öğrenin. IDOR'u kapatmak için her nesne-ID endpoint'ine bir sahiplik kontrolü ekleyin ve önbellek anahtarlarını, depolama yollarını tenant'a göre kapsamlayın.
Bir SaaS yayından önce hangi güvenlik header'lere ihtiyaç duyar?
En az: Strict-Transport-Security (HSTS), bir Content-Security-Policy, X-Content-Type-Options: nosniff, X-Frame-Options ya da frame-ancestors, Referrer-Policy ve Permissions-Policy. CSP'nizi report-only ile başlatın, ihlalleri gözden geçirin, sonra zorunlu kılın. MDN güvenlik-header'ları dokümantasyonu her biri için önerilen değerleri listeler ve yukarıdaki header tablosu her birinin neyi engellediğini özetler.
npm audit veya Snyk gibi otomatik tarama yeterli mi?
Gerekli ama yeterli değil. npm audit, Snyk ve Socket gibi araçlar bilinen CVE'leri ve kötü amaçlı paketleri yakalar ama IDOR ya da eksik bir tenant kapsamı gibi iş mantığı ve erişim kontrolü hatalarını bulamaz. Bunlar bir insan, bir test hesabı ve açık bir sahiplik kontrolü gerektirir. İkisini de çalıştırın: tarayıcıyı ve elle bir geçişi.
Özetle: Gerçekten Yayınlayabileceğiniz Bir SaaS Güvenlik Kontrol Listesi
Yayınlamak için mükemmel olmanıza gerek yok. Temele ihtiyacınız var. Önce P0 maddelerini kapatın: secret'lar paketin dışında, her sorguda tenant izolasyonu, her nesne endpoint'inde bir sahiplik kontrolü, bir kütüphane üzerinde auth ve header'larla HTTPS. Cuma günkü yayından önce tek bir şeyi düzeltecekseniz, bunu tenant izolasyonu yapın; çünkü sıfır uyarıyla bir müşterinin verisini sızdıran hata bu.
Buradaki her şey bugün çalıştırılabilir ve hiçbiri bir uyumluluk bütçesi gerektirmez. 40 kontrolü baştan sona işleyin, kod bölümlerini geliştiricinize verin ve yayınlayın. Yayına çıkmadan önce ikinci bir göz ister misiniz? Ücretsiz danışmanlık alın ve listeyi sizinle birlikte gözden geçirelim.