deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Yanlış yere konulmuş bir 'use client' direktifi, Stripe gizli anahtarını Next.js client JavaScript'ine gömdü

Bir dev.to postmortem yazısı, 'use client' dosyası içinde tanımlanan bir Next.js 15 Server Action'ın Stripe gizli anahtarını tarayıcılara nasıl gönderdiğini ve dosya ayrımının, doğrulamanın ve CI denetimlerinin bunu nasıl önlediğini anlatıyor.

Yanlış yere konulmuş bir 'use client' direktifi, Stripe gizli anahtarını Next.js client JavaScript'ine gömdü

Sızma nasıl gerçekleşti

Elena Rostova'nın dev.to'daki yazısı, yazarın araştırması istenen bir production olayını anlatıyor: Next.js 15 ile yazılmış bir uygulama, ekibin Stripe gizli anahtarını client JavaScript'inin bir parçası olarak tarayıcılara gönderiyordu. Sebep açıkta kalan bir endpoint ya da sızan bir environment dosyası değildi. Sebep, bir Server Action içeren dosyanın en üstündeki tek bir 'use client' direktifiydi.

Sorunlu modül 'use client' ile başlıyor, ardından dahili olarak 'use server' ile işaretlenmiş exported bir async function tanımlıyordu. Bu fonksiyon, projenin Stripe client'ını — gizli anahtarla başlatılan nesneyi — import ediyordu. Yazara göre Next.js böyle bir fonksiyon referansını sorunsuz şekilde serialize ediyor; ancak modül sınırın client tarafında bulunduğu için bundler, modülün importlarını takip ediyor ve kimlik bilgisi, her ziyaretçinin indirip okuyabileceği statik chunk'lara derleniyor.

Çözüm bir yama değil, mimari değişiklik

Yazıda düzeltilmiş yapı basit: ödeme action'ı kendi dosyasında yaşıyor, dosyanın ilk satırı 'use server' ve dosyanın hiçbir yerinde client direktifi yok. Client component — bir ödeme düğmesi — bu action'ı import ediyor ve bir React transition içinde çağırıyor; ancak Stripe client'ının kendisini asla import etmiyor. Client kodunu gizli anahtara bağlayan hiçbir import zinciri kalmayınca, bundler'ın takip edeceği hassas bir şey kalmıyor.

Server Action'ları public endpoint gibi ele almak

Rostova, action'ı, güvenilen dahili bir fonksiyondan çok bir API route gibi davranacak şekilde yeniden yazıyor. Action önce kimliği doğrulanmış bir session olup olmadığını kontrol ediyor ve anonim çağrıları reddediyor. Ardından, Stripe'a hiçbir şey ulaşmadan önce ham girdiyi bir Zod şemasıyla doğruluyor: tutar pozitif ve üst sınırlı olmalı, para birimi bir allowlist ile kısıtlanmalı ve idempotency anahtarı UUID olmak zorunda. Bu anahtar Stripe'a iletiliyor, böylece bir ağ yeniden denemesi yinelenen bir ödemeye yol açamıyor. Hatalar, ham exception yerine yapılandırılmış nesneler olarak çağırana döndürülüyor; bu da stack trace'leri ve dahili ayrıntıları server'da tutuyor.

İkinci tuzak: seri await'ler

Aynı yazı, bu tür kodla sık bir arada bulunan bir performans tuzağını da anlatıyor: bir server component içindeki ardışık await'ler — önce kullanıcıyı, sonra post'ları, sonra yorumları çekmek — render'ı sırayla bloke ediyor. Bağımsız bölümleri ayrı Suspense boundary'lerine sarmak, Next.js 15'in shell HTML'ini hemen göndermesini, bağımsız fetch'leri paralel başlatmasını ve her bölümü verisi geldikçe yerleştirmesini sağlıyor. Yazar, bu yeniden yapılandırmayla LCP'de yüzde 40–60 iyileşme bildiriyor; ancak bu rakam kontrollü bir benchmark'tan değil, kendi deneyiminden geliyor.

Regresyon kontrolünü otomatikleştirmek

Stripe olayından sonra ekip CI'ya bir adım ekledi: uygulamayı build et, üretilen statik chunk'lerde canlı Stripe anahtarlarını belirten sk_live_ önekini grep ile ara ve eşleşme varsa build'i başarısız kıl. Yazıya göre bu tarama, production'a ulaşmadan önce üç sızmayı daha yakaladı. Not edilmesi gereken: önek taraması yalnızca tanınabilir biçimli kimlik bilgilerini yakalar; daha geniş secret-scanning araçlarıyla eşleştirmek ağı genişletir.

Neden önemli

Server Action'lar client–server sınırını sıradan bir fonksiyon çağrısı gibi gösteriyor ve tam da bu yüzden kolayca yanlış yapılabilir. Direktif yerleşimi bir stil tercihi değildir: yanlış dosyadaki bir 'use client', modülün import ettiği her şeyi fiilen client kodu olarak yeniden sınıflandırır ve client bundle'daki her şeyin public olduğu varsayılmalıdır. Rostova'nın yaşadığı olay üç ucuz alışkanlık için yararlı bir hatırlatma — server'a özel mantığı adanmış 'use server' dosyalarında tutmak, her action'ın içinde onu bir public endpoint gibi ele alarak doğrulama ve kimlik kontrolü yapmak ve CI'da tarayıcılara gönderdiklerinizin kimlik bilgisi içermediğini teyit etmek. Next.js 15 gerekli primitive'leri sağlıyor; bunları güvenli biçimde bağlamak, yazının savunusuna göre, hâlâ geliştiricinin sorumluluğu.

  • #next-js
  • #server-actions
  • #security
  • #stripe
  • #react

İlgili yazılar