İçeriklere dön
    Siber GüvenlikGeliştiriciTeknik güvenlik rehberi

    Server Actions'ta SSRF ve DoS Risklerine Karşı Mimari Savunma

    Next.js Server Actions için authentication, authorization, girdi doğrulama, outbound allowlist, rate limit ve kaynak bütçesi yaklaşımı.

    Yayın: 23 Temmuz 2026Güncelleme: 23 Temmuz 2026InoviqLab
    Server Actions mimarisinde SSRF ve DoS risklerine karşı doğrulama, ağ izolasyonu ve hız sınırlama önlemleri
    Hedef kitle
    Geliştirici
    İçerik türü
    Teknik güvenlik rehberi
    Kaynak kontrol tarihi
    2026-07-22
    Doğrulanan sürüm veya politika
    Next.js Server Actions güvenlik dokümantasyonu ve ilgili CVE duyuruları
    Bu içerik zaman hassas teknik bilgi içerir; sürüm ve politika bilgileri yeniden kontrol edilmelidir.
    Server ActionsNext.jsSSRFDoSOWASPMimari Güvenlik

    İç bağlantılar

    Kısa özet: Next.js Server Actions, istemciden çağrılabilen public HTTP giriş noktaları olarak ele alınmalıdır. Sürüm güncellemesi zorunlu ilk adımdır; ancak tek başına yeterli değildir. Güvenli mimari; action içinde kimlik ve yetki kontrolü, sıkı girdi doğrulama, outbound istek allowlist’i, ağ çıkış kısıtlaması, rate limit, zaman aşımı, görev kuyruğu, kaynak bütçesi ve gözlemlenebilirlik katmanlarını birlikte gerektirir.

    Kısa doğrudan cevap

    Server Actions güvenliği için yalnızca action kimliklerinin tahmin edilmesinin zor olmasına veya fonksiyonun kullanıcı arayüzünde gizlenmesine güvenilmemelidir. Her Server Action:

    • Public API endpoint gibi değerlendirilmelidir.
    • Kendi authentication ve authorization kontrolünü yapmalıdır.
    • İstemciden gelen tüm girdileri doğrulamalıdır.
    • Kullanıcı tarafından belirlenen URL’lere doğrudan istek göndermemelidir.
    • Rate limit, request body limiti ve işlem süresi bütçesine sahip olmalıdır.
    • Uzun ve maliyetli işleri request içinde tamamlamak yerine kuyruğa göndermelidir.
    • Güncel ve desteklenen Next.js sürümünde çalışmalıdır.
    • Uygulama katmanının yanında ağ çıkış kurallarıyla korunmalıdır.

    Next.js, Server Actions için encrypted action ID, origin kontrolü ve varsayılan 1 MB request body limiti gibi korumalar sağlar. Ancak resmî dokümantasyon, export edilen Server Action’ların public HTTP endpoint oluşturduğunu ve her action içinde ayrıca yetkilendirme yapılması gerektiğini açıkça belirtir.

    Server Action güvenlik açısından nedir?

    Server Action, geliştirici açısından sunucuda çalışan bir fonksiyon gibi görünür. Örneğin:

    'use server'
    export async function updateProfile(formData: FormData) {
    // Veritabanı işlemleri

    } Ancak güvenlik açısından yalnızca normal bir TypeScript fonksiyonu değildir. İstemci tarafından çağrılabilen bir Server Action:

    • HTTP isteği kabul eder,
    • Kullanıcı girdisini işler,
    • Oturum bilgisine erişebilir,
    • Veritabanını değiştirebilir,
    • Harici servislere istek gönderebilir,
    • Dosya oluşturabilir,
    • E-posta veya bildirim gönderebilir,
    • Hesaplama kaynağı tüketebilir.

    Bu nedenle Server Actions, Route Handler veya klasik API endpoint’leriyle aynı tehdit modeli üzerinden değerlendirilmelidir. Next.js’in güncel authentication rehberi de Server Actions’ın public-facing API endpoint’lerle aynı güvenlik yaklaşımıyla ele alınmasını ve mutation gerçekleştirilmeden önce kullanıcının yetkili olduğunun doğrulanmasını önerir.

    SSRF ve DoS nedir?

    SSRF nedir?

    SSRF, yani Server-Side Request Forgery; saldırganın uygulama sunucusunu normalde ulaşmaması gereken bir hedefe istek göndermek için kullanabildiği güvenlik açığıdır. Riskli akış genellikle şöyledir: Kullanıcı tarafından sağlanan URL → Server Action → Sunucunun URL’ye istek göndermesi → İç servis veya beklenmeyen hedef Bu hedef:

    • Şirket içi servis,
    • Yönetim paneli,
    • Veri tabanı arayüzü,
    • Cloud metadata servisi,
    • Yerel ağ adresi,
    • Başka bir harici sistem

    olabilir. OWASP, SSRF’nin uygulamanın kendi makinesiyle, iç ağla veya harici ağlarla beklenmeyen iletişim kurması için kötüye kullanılabileceğini açıklar. URL indirme, webhook, avatar URL’si ve iç servis çağrıları yaygın risk alanları arasındadır.

    DoS nedir?

    DoS, yani Denial of Service; uygulamanın kaynaklarını tüketerek gerçek kullanıcıların hizmete ulaşmasını zorlaştırmayı veya tamamen engellemeyi amaçlar. Server Action ve Server Function katmanında tüketilebilecek kaynaklar:

    • CPU
    • Bellek
    • Request worker
    • Veri tabanı bağlantısı
    • Harici API kotası
    • Dosya depolama
    • Queue kapasitesi
    • E-posta veya SMS kotası
    • Log hacmi

    olabilir. DoS saldırısı her zaman tek bir çok büyük istekten oluşmaz. Çok sayıda küçük ama pahalı işlem de aynı sonuca yol açabilir.

    Next.js geçmişinde hangi SSRF ve DoS riskleri görüldü?

    Bu güvenlik modeli yalnızca teorik risklere dayanmıyor. Next.js ve React Server Components ekosisteminde SSRF ve kaynak tüketimiyle ilgili farklı güvenlik duyuruları yayımlandı.

    CVE-2024-34351 — Server Actions SSRF

    Mayıs 2024’te duyurulan güvenlik açığı, self-hosted Next.js uygulamalarında belirli koşullar altında Server Action yönlendirme akışının SSRF’ye yol açabilmesini kapsıyordu. Etkilenme koşulları arasında:

    • Next.js 14.1.1’den eski sürüm,
    • Self-hosted çalışma,
    • Server Actions kullanılması,
    • Action içinde / ile başlayan göreceli bir yola redirect yapılması,
    • Host header’ın manipüle edilebilmesi

    bulunuyordu. Etkilenen sürüm aralığı >=13.4 <14.1.1, düzeltilen sürüm ise 14.1.1 olarak açıklandı. Resmî workaround sunulmadı ve sürüm yükseltme önerildi.

    CVE-2026-23869 — Server Function DoS

    Nisan 2026’da yayımlanan duyuru, React Server Components paketlerini ve bunları kullanan Next.js App Router uygulamalarını etkileyen bir denial-of-service problemini açıkladı. Özel hazırlanmış bir HTTP isteği, Server Function endpoint’inde deserialize edilirken aşırı CPU tüketimine yol açabiliyordu. Etkilenen Next.js sürümleri:

    • >=13.0.0 <15.5.15
    • >=16.0 <16.2.3

    Düzeltilen sürümler:

    • 15.5.15
    • 16.2.3

    olarak açıklandı. Açık, kimlik doğrulaması gerektirmeden ağ üzerinden tetiklenebiliyor ve availability etkisi yüksek olarak değerlendiriliyordu.

    Mayıs 2026 — WebSocket upgrade üzerinden SSRF

    Mayıs 2026’da self-hosted Next.js uygulamalarında built-in Node.js server’ın WebSocket upgrade isteklerini ele alış biçiminde ayrı bir SSRF açığı duyuruldu. Etkilenen sürümler:

    • >=13.4.13 <15.5.16
    • >=16.0.0 <16.2.5

    Düzeltilen sürümler:

    • 15.5.16
    • 16.2.5

    olarak açıklandı. Duyuruya göre Vercel üzerinde çalışan deployment’lar etkilenmiyordu. Hemen yükseltme yapılamıyorsa origin sunucunun doğrudan güvenilmeyen ağlara açılmaması, gerekmiyorsa WebSocket upgrade isteklerinin reverse proxy’de engellenmesi ve internal network ile metadata servislerine outbound erişimin sınırlandırılması önerildi.

    Güncel sürüm açısından ne yapılmalı?

    Yukarıdaki güvenlik duyurularının her biri farklı sürüm aralıklarını etkiler.

    Güvenlik konusuEtkilenen sürümlerİlk düzeltilen sürümler
    Server Actions SSRF — CVE-2024-34351>=13.4 <14.1.114.1.1
    Server Function DoS — CVE-2026-23869>=13.0.0 <15.5.15 ve >=16.0 <16.2.315.5.15, 16.2.3
    WebSocket SSRF — GHSA-c4j6-fc7j-m34r>=13.4.13 <15.5.16 ve >=16.0.0 <16.2.515.5.16, 16.2.5

    Bu tablo “kullanılması gereken güncel sürümü” değil, ilgili açığın ilk düzeltildiği sürümü gösterir. Doğru yaklaşım:

    • Yalnızca minimum patched sürüme değil,
    • Kullanılan major sürümün güncel desteklenen patch sürümüne

    geçmektir. Next.js 13 veya 14 gibi eski branch’lerde kalmak yerine uygulamanın güncel destek politikası ayrıca değerlendirilmelidir.

    Sürüm yükseltme kontrolü

    npm ls next react react-dom

    Ardından:

    npm outdated
    npm audit

    gibi kontroller yapılabilir. Ancak npm audit tek başına yeterli bir güvenlik denetimi değildir. Framework güvenlik duyuruları, React upstream duyuruları ve kullanılan hosting ortamının etkilenme durumu ayrıca incelenmelidir.

    Next.js’in yerleşik Server Actions korumaları nelerdir?

    1. Encrypted ve non-deterministic action ID

    Next.js, istemcinin Server Action’a referans verebilmesi için tahmin edilmesi zor ve şifrelenmiş action ID’leri oluşturur. Ayrıca kullanılmayan Server Actions dead-code elimination yoluyla istemci bundle’ından çıkarılabilir. Ancak action ID:

    • Kimlik doğrulama değildir.
    • Yetkilendirme değildir.
    • Rate limit değildir.
    • Girdi doğrulama değildir.
    • Bir action’ın güvenli olduğunu garanti etmez.

    Action ID’nin bilinmemesine güvenmek, güvenlik sınırı olarak kabul edilmemelidir.

    2. Origin ve Host karşılaştırması

    Next.js, Server Action isteklerinde Origin header’ı ile Host veya X-Forwarded-Host değerini karşılaştırarak cross-site request risklerini azaltmaya çalışır. Varsayılan durumda yalnızca aynı origin’e izin verilir. Reverse proxy veya farklı güvenilir origin gerekiyorsa allowedOrigins yapılandırılabilir. Bu kontrol ağırlıklı olarak CSRF riskine karşıdır. allowedOrigins, Server Action’ın sunucudan hangi URL’lere istek gönderebileceğini belirleyen SSRF allowlist’i değildir. Bu iki kavram karıştırılmamalıdır:

    AyarKontrol ettiği alan
    allowedOriginsAction’ı hangi browser origin’lerinin çağırabileceği
    Outbound allowlistSunucunun hangi harici veya iç hedeflere istek gönderebileceği

    3. Varsayılan 1 MB body limiti

    Next.js, Server Action request body boyutunu varsayılan olarak 1 MB ile sınırlar. Resmî dokümantasyon bu sınırın, büyük miktarda verinin parse edilmesi nedeniyle aşırı sunucu kaynağı tüketimini ve olası DDoS riskini azaltmak için bulunduğunu belirtir. Bu limit yükseltilebilir. Ancak “dosya yüklemek çalışmıyor” gerekçesiyle sınırı kontrolsüz biçimde artırmak doğru değildir.

    Yerleşik korumalar neden yeterli değildir?

    Framework korumaları genel riskleri azaltır. Ancak uygulama aşağıdaki action’ı yazıyorsa güvenlik hâlâ geliştiricinin sorumluluğundadır:

    'use server'
    export async function importDocument(url: string) {
    const response = await fetch(url)
    const content = await response.text()
    await saveDocument(content)

    } Bu fonksiyonda şu sorular cevapsızdır:

    • Kullanıcı giriş yapmış mı?
    • Belge içe aktarma yetkisi var mı?
    • URL hangi protokolü kullanıyor?
    • Host güvenilir mi?
    • Redirect takip ediliyor mu?
    • Hedef IP iç ağda mı?
    • İstek ne kadar sürebilir?
    • İndirilecek veri ne kadar büyük?
    • Kullanıcı işlemi kaç kez çalıştırabilir?
    • Aynı işlem tekrar gönderilebilir mi?
    • İçerik güvenli mi?

    Framework’ün action ID ve Origin koruması bu soruları çözmez.

    Mimari savunma katmanları

    1. Her action içinde authentication yapın

    Kullanıcı arayüzünde butonun gizlenmesi veya sayfanın Proxy/Middleware ile korunması yeterli değildir. Server Action doğrudan çağrılabilir bir giriş noktası olarak ele alınmalıdır.

    'use server'
    import { verifySession } from '@/lib/auth'
    export async function deleteProject(projectId: string) {
    const session = await verifySession()
    if (!session) {

    throw new Error('Unauthenticated') }

    // İşlem devam eder

    } Next.js, Proxy veya üst seviye component kontrolünün tek savunma hattı olarak kullanılmamasını; Server Actions’ın kendi yetkilendirme kontrollerini yapmasını önerir.

    2. Authentication ile authorization’ı ayırın

    Kullanıcının giriş yapmış olması, işlemi gerçekleştirmeye yetkili olduğu anlamına gelmez. Örneğin bir kullanıcı:

    • Kendi şirketindeki projeyi görebilir,
    • Fakat başka tenant’ın projesini silemez.
    • Rapor oluşturabilir,
    • Fakat fiyatları değiştiremez.
    • Dosya yükleyebilir,
    • Fakat yönetici rolü atayamaz.
    const project = await db.project.findFirst({
    where: {

    id: projectId, organizationId: session.organizationId, }, })

    if (!project) {

    throw new Error('Not found') }

    if (!canDeleteProject(session.user, project)) {

    throw new Error('Forbidden') } Authorization kontrolü:

    • Action içinde,
    • Veri kaynağına yakın,
    • Güvenilir session ve database verisiyle

    yapılmalıdır. İstemciden gelen userId, role veya organizationId değerine güvenilmemelidir.

    3. Tüm girdileri sunucuda doğrulayın

    TypeScript türleri runtime güvenliği sağlamaz. Aşağıdaki tür:

    type Input = {

    amount: number destination: string } HTTP isteğinde gelen verinin gerçekten bu yapıda olduğunu garanti etmez. Runtime validation kullanılmalıdır:

    import { z } from 'zod'
    const CreatePaymentSchema = z.object({

    invoiceId: z.string().uuid(), amount: z.number().positive().max(1_000_000), currency: z.enum(['TRY', 'USD', 'EUR']), }) Action içinde:

    'use server'
    export async function createPayment(rawInput: unknown) {
    const session = await verifySession()
    if (!session) {

    throw new Error('Unauthenticated') }

    const parsed = CreatePaymentSchema.safeParse(rawInput)
    if (!parsed.success) {
    return {

    success: false, errors: parsed.error.flatten(), } }

    // Yetki ve iş kuralı kontrolleri

    } Doğrulama yalnızca formatı değil, iş kurallarını da kapsamalıdır:

    • Tutar limiti
    • Tarih aralığı
    • Liste uzunluğu
    • Metin uzunluğu
    • Dosya sayısı
    • Kullanıcının sahip olduğu kayıt
    • İşlemin mevcut durumla uyumu

    4. Kullanıcının verdiği URL’ye doğrudan fetch() yapmayın

    SSRF riskinin en temel kaynağı, istemciden gelen URL’nin sunucu tarafından doğrudan kullanılmasıdır. Riskli örnek:

    const response = await fetch(formData.get('url') as string)

    Daha güvenli yaklaşım, kullanıcının tam URL sağlamaması; sistemin önceden tanımlanmış kaynaklardan birini seçmesidir.

    const PROVIDERS = {

    accounting: 'https://api.example-accounting.com', shipping: 'https://api.example-shipping.com', } as const

    type Provider = keyof typeof PROVIDERS
    export async function syncProvider(provider: Provider) {
    const baseUrl = PROVIDERS[provider]
    return fetch(`${baseUrl}/sync`, {
    method: 'POST',

    }) } İş ihtiyacı yalnızca belirli hedeflerle iletişim gerektiriyorsa allowlist yaklaşımı kullanılmalıdır. OWASP, bilinen ve güvenilir hedeflerle iletişim kurulan senaryolarda application ve network katmanlarının birlikte allowlist yaklaşımıyla korunmasını önerir.

    5. URL kabul etmek zorundaysanız sıkı doğrulama uygulayın

    Bazı ürünlerde kullanıcı:

    • Webhook URL’si,
    • Harici görsel URL’si,
    • Feed adresi,
    • Callback endpoint’i

    girebilir. Bu durumda yalnızca URL’nin http ile başlayıp başlamadığını kontrol etmek yeterli değildir. Kontrol edilmesi gerekenler:

    • Yalnızca gerekli protokol
    • Kullanıcı adı ve parola içermemesi
    • İzin verilen portlar
    • Hostname allowlist’i
    • IP adresi formatları
    • IPv4 ve IPv6 özel ağları
    • Loopback adresleri
    • Link-local adresler
    • Cloud metadata endpoint’leri
    • Redirect hedefleri
    • DNS çözümlemesinin sonucu
    • Response boyutu
    • İstek süresi

    Basit bir uygulama katmanı örneği:

    const ALLOWED_HOSTS = new Set([

    'images.example-cdn.com', 'hooks.trusted-partner.com', ])

    function validateOutboundUrl(input: string): URL {
    const url = new URL(input)
    if (url.protocol !== 'https:') {

    throw new Error('Only HTTPS is allowed') }

    if (!ALLOWED_HOSTS.has(url.hostname)) {

    throw new Error('Host is not allowed') }

    if (url.username || url.password) {

    throw new Error('Credentials in URL are not allowed') }

    if (url.port && url.port !== '443') {

    throw new Error('Port is not allowed') }

    return url

    } İstek:

    const url = validateOutboundUrl(input)
    const response = await fetch(url, {
    redirect: 'manual',
    signal: AbortSignal.timeout(5_000),

    }) Bu örnek tek başına tam SSRF koruması değildir. DNS rebinding, proxy davranışı ve ağ yönlendirmesi gibi riskler nedeniyle application validation mutlaka network egress kontrolüyle desteklenmelidir. OWASP ayrıca validation bypass riskini azaltmak için redirect takibinin kapatılmasını ve IP/domain doğrulamasının battle-tested kütüphanelerle yapılmasını önerir.

    6. Outbound ağ erişimini sınırlayın

    En güçlü SSRF savunmalarından biri, uygulamanın ağ üzerinden zaten ulaşmaması gereken hedeflere erişememesidir. Uygulama container veya sunucusu yalnızca:

    • Gereken veri tabanına,
    • Onaylı API’lere,
    • Gerekli depolama servisine,
    • İzin verilen e-posta veya ödeme servisine

    erişebilmelidir. Kısıtlanabilecek alanlar:

    • Private subnet aralıkları
    • Loopback
    • Link-local ağlar
    • Cloud metadata servisleri
    • Yönetim portları
    • Şirket içi dashboard’lar
    • Kubernetes veya container yönetim API’leri
    • Gereksiz outbound protokoller

    Uygulanabilecek kontroller:

    • Firewall
    • Security group
    • Network policy
    • Egress proxy
    • Service mesh policy
    • Reverse proxy
    • Cloud metadata koruması

    OWASP, SSRF’ye karşı defense-in-depth yaklaşımında application validation’ın yanında ağ katmanında yalnızca meşru trafik akışlarına izin verilmesini önerir.

    7. allowedOrigins listesini gereksiz genişletmeyin

    Reverse proxy arkasında çalışan uygulamalarda ek güvenilir origin tanımlamak gerekebilir. Örnek: /** @type {import('next').NextConfig} */

    module.exports = {

    experimental: { serverActions: { allowedOrigins: [ 'app.example.com', 'admin.example.com', ], }, }, } Wildcard kullanımı gerekiyorsa mümkün olduğunca dar tutulmalıdır. Riskli yaklaşım: allowedOrigins: ['*'] veya işletmenin kontrolünde olmayan geniş domain kalıplarına izin verilmesidir. allowedOrigins ayarı CSRF benzeri cross-origin çağrı riskini yönetir; action’ın outbound hedeflerini sınırlamaz.

    8. Request body limitini iş ihtiyacına göre küçültün

    Next.js’in varsayılan Server Action body limiti 1 MB’dir. Basit bir form yalnızca birkaç kilobyte veri gerektiriyorsa limiti yükseltmek yerine mevcut sınırı korumak veya mimariyi değiştirmek daha güvenli olabilir. /** @type {import('next').NextConfig} */

    module.exports = {

    experimental: { serverActions: { bodySizeLimit: '500kb', }, }, } Resmî dokümantasyon, limitin büyük request parse işlemlerinin kaynak tüketimini ve DDoS riskini azaltmak amacıyla bulunduğunu belirtir.

    Büyük dosyalar nasıl yüklenmeli?

    Çok büyük dosyayı Server Action üzerinden uygulama sunucusuna geçirmek yerine:

    • Action kullanıcıyı doğrular.
    • Dosya türü ve boyut limitini belirler.
    • Kısa süreli signed upload URL üretir.
    • İstemci dosyayı doğrudan object storage’a yükler.
    • Backend yüklemeyi doğrular.
    • Gerekirse zararlı dosya taraması yapılır.
    • İşlem sonucu ayrı bir kayıtla tamamlanır.

    Bu yaklaşım uygulama worker’ının büyük dosya transferi boyunca meşgul kalmasını azaltır.

    9. Rate limit’i tek katmanda bırakmayın

    Server Actions için rate limit en az iki katmanda uygulanabilir:

    Edge veya gateway katmanı

    • IP bazlı limit
    • Bot ve saldırı trafiği filtreleme
    • Bölgesel kural
    • Request boyutu
    • Ani trafik artışı
    • Web Application Firewall

    Uygulama katmanı

    • Kullanıcı bazlı limit
    • Tenant bazlı limit
    • Action bazlı limit
    • İşlem maliyetine göre kota
    • Ücretsiz ve ücretli paket ayrımı
    • Günlük operasyon sınırı

    Örnek kavramsal kontrol:

    await rateLimit.consume({

    key: `${session.userId}:generate-report`, limit: 5, windowSeconds: 60, }) Aynı kullanıcı bir action’ı beş kez çağırabiliyor olabilir; ancak her çağrı çok sayıda veri tabanı sorgusu veya yapay zekâ isteği üretiyorsa yalnızca request sayısı yeterli metrik değildir. Maliyet bazlı limit de gerekebilir: Basit profil güncelleme = 1 kredi Büyük rapor üretme = 20 kredi Toplu dosya işleme = 100 kredi

    10. İşlem süresi ve kaynak bütçesi belirleyin

    Her Server Action için şu bütçeler tanımlanmalıdır:

    • Maksimum request süresi
    • Maksimum database sorgu süresi
    • Maksimum outbound API süresi
    • Maksimum response boyutu
    • Maksimum kayıt sayısı
    • Maksimum paralel işlem
    • Maksimum retry
    • Maksimum dosya boyutu

    Örnek timeout:

    const response = await fetch(apiUrl, {
    signal: AbortSignal.timeout(5_000),

    }) Veri tabanında da:

    • Statement timeout
    • Connection pool limiti
    • Transaction süresi
    • Pagination zorunluluğu

    uygulanmalıdır. Riskli sorgu:

    await db.order.findMany()

    Daha kontrollü sorgu:

    await db.order.findMany({
    where: {

    organizationId: session.organizationId, },

    take: 100,
    orderBy: {

    createdAt: 'desc', }, })

    11. Uzun işleri Server Action içinde bitirmeyin

    Aşağıdaki işler request-response döngüsünde tamamlanmak için uygun olmayabilir:

    • Büyük PDF üretimi
    • Binlerce satırlık export
    • Video dönüştürme
    • Toplu e-posta
    • AI raporu
    • Çok sayıda API senkronizasyonu
    • Büyük veri import’u
    • Görsel işleme

    Daha güvenli akış: Server Action → Authentication → Authorization → Validation → Kota kontrolü → Job kaydı oluşturma → Queue’ya gönderme → Kullanıcıya job ID dönme Worker: Queue → Concurrency limiti → Timeout → Retry politikası → Sonuç kaydı → Kullanıcı bildirimi Bu model, bir request’in uygulama worker’ını uzun süre meşgul etmesini azaltır. Ancak queue kullanmak DoS riskini otomatik olarak ortadan kaldırmaz. Şunlar ayrıca sınırlandırılmalıdır:

    • Kullanıcı başına aktif job
    • Queue toplam uzunluğu
    • Job payload boyutu
    • Worker concurrency
    • Retry sayısı
    • Job yaşam süresi
    • Aynı işin tekrar oluşturulması

    12. Idempotency ve tekrar koruması kullanın

    Kullanıcı aynı formu:

    • Çift tıklayabilir,
    • Ağ sorunu nedeniyle tekrar gönderebilir,
    • Tarayıcı geri dönüşüyle yeniden çalıştırabilir,
    • Kötü niyetli olarak tekrar tekrar çağırabilir.

    Özellikle şu işlemlerde idempotency gerekir:

    • Ödeme
    • Sipariş
    • Rezervasyon
    • E-posta
    • Fatura
    • Toplu işlem
    • Harici API çağrısı

    Örnek yapı: Idempotency key + kullanıcı + action türü + geçerlilik süresi Aynı key daha önce işlendiğinde yeni işlem oluşturmak yerine önceki sonuç döndürülmelidir.

    13. Client’tan gelen kimlik bilgilerini gerçek kaynak kabul etmeyin

    Riskli örnek:

    export async function updateUser(input: {

    userId: string

    role: 'admin' | 'user'

    }) {

    await db.user.update({
    where: { id: input.userId },
    data: { role: input.role },

    }) } Güvenli yaklaşım:

    • İşlemi yapan kullanıcı session’dan alınır.
    • Hedef kayıt tenant kapsamında aranır.
    • Rol değiştirme yetkisi sunucu tarafında doğrulanır.
    • Atanabilecek roller allowlist ile sınırlandırılır.
    • İşlem audit log’a yazılır.
    const session = await verifySession()
    if (!session || session.role !== 'owner') {

    throw new Error('Forbidden') }

    const targetUser = await db.user.findFirst({
    where: {

    id: input.userId, organizationId: session.organizationId, }, })

    14. DTO ve Data Access Layer kullanın

    Next.js, authorization mantığının veri kaynağına yakın merkezi bir Data Access Layer içinde tutulmasını ve istemciye yalnızca gerekli alanların DTO üzerinden gönderilmesini önerir. Riskli dönüş:

    return user

    Daha kontrollü dönüş:

    return {

    id: user.id, name: user.name, avatarUrl: user.avatarUrl, } Şunlar istemciye yanlışlıkla gönderilmemelidir:

    • Parola hash’i
    • Internal role flag’leri
    • Secret token
    • Ödeme sağlayıcısı kimlikleri
    • Özel notlar
    • Başka tenant verileri
    • Sunucu yapılandırmaları

    15. Self-hosted origin’i doğrudan internete açmayın

    Özellikle self-hosted Next.js uygulamalarında: İnternet → Reverse proxy / load balancer / WAF → Next.js origin yaklaşımı tercih edilebilir. Origin sunucunun doğrudan public IP üzerinden erişilebilir olması:

    • Proxy güvenlik kurallarının aşılması,
    • Host header davranışlarının farklılaşması,
    • Rate limit’in bypass edilmesi,
    • WebSocket veya upgrade isteklerinin doğrudan ulaşması

    gibi riskleri artırabilir. Mayıs 2026 WebSocket SSRF duyurusunda da yükseltme mümkün değilse origin’in güvenilmeyen ağlara doğrudan açılmaması ve WebSocket gerekmiyorsa proxy veya load balancer’da engellenmesi önerildi.

    Güvenli Server Action örneği

    Aşağıdaki örnek, tek başına bütün güvenlik kontrollerini çözmez; ancak katmanların nasıl bir araya getirilebileceğini gösterir.

    'use server'
    import { z } from 'zod'
    import { verifySession } from '@/lib/auth'
    import { db } from '@/lib/db'
    import { rateLimit } from '@/lib/rate-limit'
    import { jobs } from '@/lib/jobs'
    const ReportSchema = z.object({

    projectId: z.string().uuid(), format: z.enum(['pdf', 'xlsx']), })

    export async function requestProjectReport(rawInput: unknown) {
    // 1. Authentication
    const session = await verifySession()
    if (!session) {
    return {

    success: false, code: 'UNAUTHENTICATED', } }

    // 2. Runtime validation
    const parsed = ReportSchema.safeParse(rawInput)
    if (!parsed.success) {
    return {

    success: false, code: 'INVALID_INPUT', errors: parsed.error.flatten(), } }

    // 3. Rate and quota limit
    await rateLimit.consume({

    key: `${session.organizationId}:${session.userId}:report`, limit: 5, windowSeconds: 60, })

    // 4. Tenant-scoped data access
    const project = await db.project.findFirst({
    where: {

    id: parsed.data.projectId, organizationId: session.organizationId, },

    select: {

    id: true, status: true, }, })

    if (!project) {
    return {

    success: false, code: 'NOT_FOUND', } }

    // 5. Authorization
    if (!session.permissions.includes('report:create')) {
    return {

    success: false, code: 'FORBIDDEN', } }

    // 6. Queue instead of expensive synchronous work
    const job = await jobs.enqueue('project-report', {

    organizationId: session.organizationId, requestedBy: session.userId, projectId: project.id, format: parsed.data.format, })

    // 7. Return minimal data
    return {

    success: true, jobId: job.id, } } Bu örnekte:

    • Kimlik doğrulama action içinde yapılır.
    • Runtime input validation bulunur.
    • Kullanıcı ve tenant bazlı limit uygulanır.
    • Veri sorgusu tenant ile sınırlandırılır.
    • Yetki ayrıca kontrol edilir.
    • Pahalı işlem kuyruğa gönderilir.
    • İstemciye minimum sonuç döndürülür.

    SSRF savunma karar tablosu

    İş ihtiyacıÖnerilen yaklaşım
    Yalnızca bir harici API’ye istekURL’yi kod içinde sabitleyin
    Birkaç güvenilir servisHost allowlist kullanın
    Kullanıcı webhook tanımlarHTTPS, host/IP kontrolü, egress proxy ve doğrulama token’ı
    Kullanıcı harici görsel URL’si girerProxy indirme yerine doğrudan upload değerlendirin
    Herhangi bir internet URL’si desteklenecekAyrı sandboxed fetch servisi ve sıkı ağ politikası
    İç servis çağrısıService identity ve network policy kullanın
    Cloud ortamıMetadata servisine erişimi sınırlandırın
    Redirect gerekliHer redirect hedefini yeniden doğrulayın
    DNS tabanlı hedefÇözümlenen IP’yi ve ağ sınıfını kontrol edin

    DoS savunma karar tablosu

    RiskMimari savunma
    Büyük request bodyDüşük body limiti ve doğrudan object storage upload
    Çok sayıda action çağrısıEdge + kullanıcı + tenant rate limit
    Pahalı CPU işlemiQueue ve worker concurrency limiti
    Uzun harici API isteğiTimeout, circuit breaker ve sınırlı retry
    Büyük database sorgusuPagination, statement timeout ve index
    Toplu exportAsenkron job ve dosya yaşam süresi
    Tekrarlanan ödeme/siparişIdempotency key
    Queue’nun doldurulmasıKullanıcı başına aktif job ve queue limiti
    Log hacmi saldırısıLog sampling, boyut ve saklama limiti
    Çok sayıda başarısız authIP/kullanıcı limiti ve alarm

    Gözlemlenebilirlik nasıl kurulmalı?

    SSRF veya DoS girişimini yalnızca önlemek değil, erken fark etmek de gerekir.

    İzlenmesi gereken metrikler

    • Action başına istek sayısı
    • P95 ve P99 işlem süresi
    • Request body boyutu
    • CPU ve memory kullanımı
    • Event loop gecikmesi
    • Database pool doluluğu
    • Action başına sorgu sayısı
    • Outbound istek hedefleri
    • Outbound timeout oranı
    • Queue uzunluğu
    • Aktif worker sayısı
    • Rate limit reddi
    • 401 ve 403 oranı
    • 429 oranı
    • 5xx hata oranı
    • Kullanıcı ve tenant başına maliyet

    Alarm örnekleri

    • Belirli action’da dakikalık çağrı sayısı olağandışı arttı.
    • İç IP aralığına outbound bağlantı denendi.
    • Metadata servisine erişim girişimi görüldü.
    • Action P99 süresi normalin üç katına çıktı.
    • Queue uzunluğu eşik değerini aştı.
    • Aynı kullanıcı çok sayıda rapor job’ı oluşturdu.
    • Database pool sürekli dolu.
    • Bir action sürekli timeout oluyor.

    Loglarda bulunabilecek alanlar

    • Request ID
    • Action türü
    • Kullanıcı ID
    • Tenant ID
    • Sonuç kodu
    • İşlem süresi
    • Rate limit sonucu
    • Outbound servis adı
    • Job ID
    • Hata sınıfı

    Parola, session token, tam kredi kartı verisi veya hassas form içeriği loglara yazılmamalıdır.

    Test planı

    Authentication testleri

    • Oturumsuz kullanıcı action’ı çağırabiliyor mu?
    • Süresi dolmuş session kabul ediliyor mu?
    • İptal edilmiş session çalışıyor mu?
    • Client tarafında gizlenmiş action doğrudan çağrılabiliyor mu?

    Authorization testleri

    • Kullanıcı başka tenant kaydını değiştirebiliyor mu?
    • Normal kullanıcı yönetici işlemi yapabiliyor mu?
    • URL veya form içindeki organizationId değiştirildiğinde ne oluyor?
    • Silinmiş veya pasif kullanıcı action çağırabiliyor mu?

    SSRF testleri

    • İzin verilmeyen host reddediliyor mu?
    • HTTP protokolü reddediliyor mu?
    • Redirect hedefi tekrar doğrulanıyor mu?
    • Private ve loopback ağlara erişim engelleniyor mu?
    • Cloud metadata erişimi ağ katmanında kapalı mı?
    • DNS sonucu değiştiğinde kontrol devam ediyor mu?

    DoS testleri

    • Body limitinden büyük istek reddediliyor mu?
    • Aynı kullanıcı limiti aşınca 429 alıyor mu?
    • Pahalı action paralel çağrıldığında sistem ayakta kalıyor mu?
    • Harici API yanıt vermediğinde timeout çalışıyor mu?
    • Queue kapasitesi dolunca kontrollü hata dönüyor mu?
    • Büyük veri export’u request worker’ını bloke ediyor mu?

    Operasyon testleri

    • Rate limit store çalışmazsa sistem fail-open mı, fail-closed mu?
    • Reverse proxy gerçek client IP bilgisini doğru iletiyor mu?
    • Origin doğrudan internete erişilebilir mi?
    • Deployment sırasında action encryption key uyumu korunuyor mu?
    • Alarm ve olay bildirimleri doğru kişiye ulaşıyor mu?

    Üretim öncesi kontrol listesi

    Sürüm ve bağımlılıklar

    • Next.js desteklenen güncel patch sürümünde mi?
    • React ve React Server Components paketleri güncel mi?
    • Framework güvenlik duyuruları kontrol edildi mi?
    • Kullanılan major sürüm hâlâ destekleniyor mu?
    • Lockfile güncel mi?
    • Dependency taraması CI içinde çalışıyor mu?

    Authentication ve authorization

    • Her Server Action session doğruluyor mu?
    • Her mutation ayrıca authorization yapıyor mu?
    • Tenant kontrolü veri sorgusunda uygulanıyor mu?
    • Client’tan gelen role ve tenant ID’ye güvenilmiyor mu?
    • Yetki kontrolleri Data Access Layer’da merkezileştirildi mi?
    • Kritik işlemler audit log’a yazılıyor mu?

    Girdi doğrulama

    • Runtime schema validation var mı?
    • Metin uzunlukları sınırlı mı?
    • Liste ve dosya sayıları sınırlı mı?
    • UUID ve enum alanları doğrulanıyor mu?
    • İş kuralları sunucuda kontrol ediliyor mu?
    • Hata mesajları hassas bilgi sızdırmıyor mu?

    SSRF

    • Action kullanıcı URL’sine doğrudan fetch yapıyor mu?
    • Güvenilir hedefler allowlist ile sınırlandırıldı mı?
    • Yalnızca gerekli protokoller açık mı?
    • Redirect otomatik takip edilmiyor mu?
    • Private, loopback ve metadata ağları engelli mi?
    • Outbound firewall veya egress policy var mı?
    • DNS ve IP kontrolleri IPv4 ile IPv6’yı kapsıyor mu?
    • Response boyutu ve timeout sınırı var mı?

    DoS

    • bodySizeLimit iş ihtiyacına uygun mu?
    • Edge rate limit var mı?
    • Kullanıcı ve tenant bazlı limit var mı?
    • Pahalı işlemler queue üzerinden mi çalışıyor?
    • Worker concurrency limiti var mı?
    • Harici isteklerde timeout var mı?
    • Database statement timeout var mı?
    • Pagination zorunlu mu?
    • Retry sayısı sınırlı mı?
    • Idempotency uygulanıyor mu?

    Self-hosting

    • Origin sunucu doğrudan internete kapalı mı?
    • Reverse proxy Host header’ı kontrollü iletiyor mu?
    • WebSocket yalnızca gerekiyorsa açık mı?
    • Reverse proxy body ve request limitleri uyguluyor mu?
    • Metadata ve internal service egress erişimi sınırlı mı?
    • Next.js instance’ları aynı action encryption key’i kullanıyor mu?
    • Proxy, load balancer ve uygulama logları ilişkilendirilebiliyor mu?

    İzleme

    • Action latency ölçülüyor mu?
    • Rate limit reddi izleniyor mu?
    • Outbound hedefler loglanıyor mu?
    • Queue uzunluğu izleniyor mu?
    • CPU, memory ve event loop alarmı var mı?
    • Database pool alarmı var mı?
    • Olay müdahale sorumluları belli mi?
    • Güvenlik olayları için runbook var mı?

    InoviqLab değerlendirmesi

    Bu bölüm InoviqLab’ın teknik değerlendirmesidir; Next.js ve OWASP’ın resmî açıklamalarından ayrıdır. Server Actions güvenliğinde en sık yapılan hata, fonksiyonun yalnızca uygulamanın belirli bir component’inden çağrıldığı için özel veya erişilemez olduğunu düşünmektir. Action kullanıcı arayüzünde görünmese bile HTTP giriş noktası olarak değerlendirilmelidir. İkinci hata, framework’ün yerleşik korumalarını uygulama güvenliğiyle eşitlemektir. Next.js:

    • Action ID üretir,
    • Origin kontrolü yapar,
    • Varsayılan body limiti uygular.

    Ancak uygulamanın:

    • Kullanıcı yetkisini,
    • Tenant sınırını,
    • URL hedefini,
    • İşlem maliyetini,
    • Harici servis kotasını

    bilmez. Üçüncü hata, SSRF’yi yalnızca URL validation problemi olarak görmektir. Application validation gereklidir; ancak tek başına yeterli değildir. Sağlıklı SSRF savunması: İş ihtiyacını sınırlandırma + URL ve host allowlist + Redirect kontrolü + DNS ve IP doğrulama + Outbound ağ kısıtlaması + Timeout ve response limiti + İzleme katmanlarından oluşur. Dördüncü hata, rate limit’in yalnızca IP bazlı kurulmasıdır. Kurumsal ağlarda binlerce kullanıcı aynı IP’yi paylaşabilir. Saldırgan ise farklı IP’ler kullanabilir. Bu nedenle limit:

    • IP,
    • Kullanıcı,
    • Tenant,
    • Action,
    • İşlem maliyeti

    boyutlarında düşünülmelidir. Beşinci hata, uzun işlemlerin Server Action içinde tamamlanmasıdır. Server Action:

    • İşlemi doğrulamak,
    • Yetkiyi kontrol etmek,
    • Job oluşturmak

    için kullanılabilir. Dakikalar süren rapor, import veya AI çalışması ayrı worker üzerinde yürütülmelidir. Altıncı hata, güvenlik açığı düzeltildiğinde mimari kontrollerin gereksiz olduğunun düşünülmesidir. Patch belirli framework zafiyetini kapatır. Mimari savunma ise:

    • Gelecekteki framework açıklarını,
    • Uygulama kodundaki hataları,
    • Yanlış yapılandırmayı,
    • Kötüye kullanılan meşru işlemleri

    sınırlamaya yardımcı olur. InoviqLab açısından güvenli Server Actions modeli şu sırayla kurulmalıdır:

    • Desteklenen güncel sürüm
    • Her action içinde authentication
    • Veri kaynağına yakın authorization
    • Runtime input validation
    • Tenant-scoped sorgular
    • Outbound URL allowlist
    • Network egress kontrolü
    • Request ve işlem bütçeleri
    • Rate limit ve kota
    • Uzun işler için queue
    • Idempotency
    • İzleme ve olay müdahalesi

    Sonuç

    Server Actions, geliştirici deneyimini kolaylaştırır; ancak güvenlik sorumluluğunu ortadan kaldırmaz. Her Server Action:

    • Public endpoint gibi ele alınmalı,
    • Kullanıcıyı doğrulamalı,
    • İşlem yetkisini kontrol etmeli,
    • Girdiyi runtime’da doğrulamalı,
    • Kaynak tüketimini sınırlandırmalı,
    • Harici ağ erişimini kontrol etmeli,
    • İzlenebilir olmalıdır.

    SSRF’ye karşı:

    • Kullanıcı tarafından verilen URL’leri sınırlayın.
    • Allowlist kullanın.
    • Redirect’leri kontrol edin.
    • Private ağ ve metadata erişimini engelleyin.
    • Outbound egress policy uygulayın.

    DoS’a karşı:

    • Güncel patch sürümünde kalın.
    • Body ve rate limit uygulayın.
    • Timeout belirleyin.
    • Büyük işleri kuyruğa taşıyın.
    • Database ve worker kaynaklarını sınırlandırın.
    • Tekrarlanan işlemler için idempotency kullanın.

    En önemli yaklaşım şudur: Framework güvenliği ilk katmandır; uygulama ve altyapı mimarisi diğer katmanları oluşturur.

    Kaynaklar

    • - Next.js — Server Actions güvenlik ve veri güvenliği rehberi
    • - Next.js — allowedOrigins ve bodySizeLimit yapılandırması
    • - Next.js Security Advisory — Server Actions SSRF, CVE-2024-34351
    • - Next.js Security Advisory — Server Components DoS, CVE-2026-23869
    • - Next.js Security Advisory — WebSocket upgrade SSRF
    • - OWASP — Server-Side Request Forgery Prevention Cheat Sheet
    • - Next.js — Production ve authentication güvenlik kontrolleri
    • Planlanan ilk yayın: InoviqLab toplu içerik yayın günüKaynak kontrol tarihi: 23 Temmuz 2026Önerilen güncelleme: Her Next.js güvenlik duyurusunda ve en geç Ocak 2027’de

    Paylaş