- Konu sahibi
- #1
Bir Next.js uygulamasında ortam değişkeni, tarayıcıya gönderilen JavaScript koduna veya tarayıcının okuyabildiği bir HTTP yanıtına girerse istemciye sızmış olur. En yaygın neden, değişken adını
Next.js, istemci tarafında kullanılmak üzere işaretlenen bazı ortam değişkenlerinin değerini derleme sırasında JavaScript çıktısına yerleştirir. Örneğin:
Bu değer istemci kodunda kullanıldığında tarayıcıya gönderilen paket içinde bulunabilir. Standart Next.js davranışında öneksiz sunucu değişkeni istemcide kullanılabilir kalmaz; belgelenen sınırda boş değerle değiştirilir. İstemci kodunda process.env.DATABASE_PASSWORD yazmak tek başına gerçek parolayı otomatik yayımlamaz. Ancak next.config.js env alanına konulan değerler önekten bağımsız olarak pakete girebilir; sunucunun yanıta koyduğu sır da açılır.
Aşağıdaki hatalı isimlendirmede değer açıkça yayımlanır; gerçek parola yerine yalnız sahte deneme değeriyle düşünün:
Bu önek, gizli tutma koruması değil istemciye açma işaretidir. Ayrıca sunucu tarafındaki bir route şu tür bir yanıt döndürürse değer yine tarayıcıya açılır:
Burada sorun ortam değişkeninin okunması değil, gizli değerin HTTP yanıtına konulmasıdır.
Değişkenin tarayıcıda bilinmesinde sakınca yoksa açıkça istemci değişkeni olarak adlandırılabilir. Gizli kimlik bilgileri, imzalama anahtarları, veritabanı bağlantıları ve sunucu içi servis anahtarları ise yalnızca sunucu kodunda kullanılmalıdır.
Açık kabul edilen bir anahtar bile sızıntı sayılmayabilir; ancak bu anahtarın yetkileri sınırlı olmalı, yönetim veya veritabanı erişimi vermemelidir. Bir değer gizli tutulamıyorsa onu gizliymiş gibi korumaya çalışmak yerine yetkisini azaltmak gerekir.
Aşağıdaki tamamlanmış Route Handler dış servise bağlanmaz, anahtarın varlığını kontrol edip sabit deneme özeti döndürür. Gerçek rapor üretmez; total alanındaki 3 bir ölçüm değildir:
Beklenen sonuç, tarayıcının
“NEXT_PUBLIC yazmadıysam kesinlikle güvendeyim” düşüncesi: Gizli değer yine API yanıtı, HTML'e gömülen başlangıç verisi, hata mesajı veya istemciye aktarılan yapılandırma yoluyla açılabilir.
İstemciye gizli değerin tamamını gönderip arayüzde filtrelemek: Filtreleme tarayıcıda yapıldığı için kullanıcı geliştirici araçlarıyla ham değeri görebilir. Filtreleme sunucuda yapılmalıdır.
İstemciye açık anahtarı sunucu sırrıyla karıştırmak: Bir sağlayıcının tarayıcıda kullanılmak üzere tasarladığı sınırlı anahtar ile yönetim yetkili gizli anahtar aynı şey değildir. Yetki kapsamını ayrıca kontrol edin.
Anahtarı değiştirmeden yalnızca kodu düzeltmek: Bir sır istemciye çıktıysa ele geçirilmiş kabul edilmeli, erişimi iptal edilmeli ve yeni değer güvenli sunucu yapılandırmasına alınmalıdır.
NEXT_PUBLIC_ ile başlatmak , next.config.js içindeki env seçeneğine eklemek veya sunucuda okunan sırrı yanıta taşımaktır. Sunucuda çalışan kodda tutulan ve istemciye aktarılan yanıtların içine eklenmeyen değişkenler tarayıcıya gönderilmez.Sızıntı nasıl oluşur?
Next.js, istemci tarafında kullanılmak üzere işaretlenen bazı ortam değişkenlerinin değerini derleme sırasında JavaScript çıktısına yerleştirir. Örneğin:
Kod:
const analyticsId = process.env.NEXT_PUBLIC_ANALYTICS_ID;
Bu değer istemci kodunda kullanıldığında tarayıcıya gönderilen paket içinde bulunabilir. Standart Next.js davranışında öneksiz sunucu değişkeni istemcide kullanılabilir kalmaz; belgelenen sınırda boş değerle değiştirilir. İstemci kodunda process.env.DATABASE_PASSWORD yazmak tek başına gerçek parolayı otomatik yayımlamaz. Ancak next.config.js env alanına konulan değerler önekten bağımsız olarak pakete girebilir; sunucunun yanıta koyduğu sır da açılır.
Aşağıdaki hatalı isimlendirmede değer açıkça yayımlanır; gerçek parola yerine yalnız sahte deneme değeriyle düşünün:
Kod:
// app/page.jsx
'use client';
export default function Page() {
const config = {
databasePassword: process.env.NEXT_PUBLIC_DATABASE_PASSWORD
};
return <pre>{JSON.stringify(config)}</pre>;
}
Bu önek, gizli tutma koruması değil istemciye açma işaretidir. Ayrıca sunucu tarafındaki bir route şu tür bir yanıt döndürürse değer yine tarayıcıya açılır:
Kod:
return Response.json({
apiBaseUrl: process.env.API_BASE_URL,
apiKey: process.env.INTERNAL_API_KEY
});
Burada sorun ortam değişkeninin okunması değil, gizli değerin HTTP yanıtına konulmasıdır.
Gizli ve istemciye açık değişkenleri ayırma
Değişkenin tarayıcıda bilinmesinde sakınca yoksa açıkça istemci değişkeni olarak adlandırılabilir. Gizli kimlik bilgileri, imzalama anahtarları, veritabanı bağlantıları ve sunucu içi servis anahtarları ise yalnızca sunucu kodunda kullanılmalıdır.
| Değişken türü | Örnek | İstemciye gönderilebilir mi? | Doğru kullanım |
|---|---|---|---|
| Genel istemci ayarı | NEXT_PUBLIC_ANALYTICS_ID | Evet, bilerek açık tasarlanır | İstemci bileşeninde sınırlı kullanım |
| Sunucu sırrı | DATABASE_PASSWORD | Hayır | Sunucu route'u veya server-only modül |
| Kullanıcıya özel veri | Oturum veya hesap bilgisi | Yalnız gerekli alanlar | Sunucuda doğrulayıp filtrelenmiş yanıt döndürme |
Açık kabul edilen bir anahtar bile sızıntı sayılmayabilir; ancak bu anahtarın yetkileri sınırlı olmalı, yönetim veya veritabanı erişimi vermemelidir. Bir değer gizli tutulamıyorsa onu gizliymiş gibi korumaya çalışmak yerine yetkisini azaltmak gerekir.
Uygulanabilir kontrol ve düzeltme adımları
- Ortam dosyalarındaki değişkenleri iki gruba ayırın.
NEXT_PUBLIC_ile başlayanları istemciye açık kabul edin; diğerlerini varsayılan olarak gizli kabul edin. - İstemci bileşenlerinde gizli değişken okuyan ifadeleri kaldırın. Gizli değeri gereken işlem bir sunucu route'una veya yalnız sunucuda çalışan bir modüle taşıyın.
- Sunucu route'unda istemciye dönen nesneyi elle oluşturun. Tüm ortam nesnesini veya yapılandırma nesnesini doğrudan JSON'a çevirmeyin.
- Gerçek sırrı arama/günlük kayıtlarına kopyalamak yerine sahte ve ayırt edilebilir deneme değeriyle paket ve Network kontrolü yapın. Değer görünüyorsa yalnız kodu düzeltmek yeterli değildir; daha önce kullanılmış anahtarı da geçersiz kılıp yenileyin.
- Gizli değişkenin derleme sırasında istemci çıktısına yerleştirilmiş olabileceğini hesaba katın. Değişkeni sonradan silmek, daha önce dağıtılmış JavaScript dosyalarını veya istemcinin aldığı yanıtları geri almaz.
Aşağıdaki tamamlanmış Route Handler dış servise bağlanmaz, anahtarın varlığını kontrol edip sabit deneme özeti döndürür. Gerçek rapor üretmez; total alanındaki 3 bir ölçüm değildir:
Kod:
// app/api/report/route.js
export async function GET() {
const key = process.env.INTERNAL_REPORT_KEY;
if (!key) {
return Response.json({ error: "Yapılandırma eksik" }, { status: 503 });
}
return Response.json({ status: "ornek", total: 3 });
}
Beklenen sonuç, tarayıcının
status ve total alanlarını alması; INTERNAL_REPORT_KEY değerini hiçbir JavaScript paketi, HTML çıktısı veya Network yanıtında görmemesidir. Kullanıcıya özel rapor eklenirse ayrıca kimlik, yetki ve uygun önbellek kontrolü gerekir; anahtarın varlığı kullanıcı yetkilendirmesi değildir. Anahtar görünüyorsa route'un döndürdüğü nesneyi, çağrılan yardımcı fonksiyonun sonucunu ve istemci paketine giren import zincirini inceleyin.Sık yapılan hatalar
“NEXT_PUBLIC yazmadıysam kesinlikle güvendeyim” düşüncesi: Gizli değer yine API yanıtı, HTML'e gömülen başlangıç verisi, hata mesajı veya istemciye aktarılan yapılandırma yoluyla açılabilir.
İstemciye gizli değerin tamamını gönderip arayüzde filtrelemek: Filtreleme tarayıcıda yapıldığı için kullanıcı geliştirici araçlarıyla ham değeri görebilir. Filtreleme sunucuda yapılmalıdır.
İstemciye açık anahtarı sunucu sırrıyla karıştırmak: Bir sağlayıcının tarayıcıda kullanılmak üzere tasarladığı sınırlı anahtar ile yönetim yetkili gizli anahtar aynı şey değildir. Yetki kapsamını ayrıca kontrol edin.
Anahtarı değiştirmeden yalnızca kodu düzeltmek: Bir sır istemciye çıktıysa ele geçirilmiş kabul edilmeli, erişimi iptal edilmeli ve yeni değer güvenli sunucu yapılandırmasına alınmalıdır.