Aikido

SQL'de SELECT * kullanımından nasıl kaçınılır: veri sızıntılarını önleme

Performans

Kural
SQL sorgularında SELECT * kullanmaktan kaçının.
Üretim (production) kodunda SELECT * kullanımı, uygulamaları şema değişikliklerine karşı kırılgan hale getirir ve veri bağımlılıklarını gizler.

Desteklenen diller: 45+

Giriş

Üretim (production) sorgularında SELECT * ifadesini kullanmak, uygulamanızın kullanmadığı sütunlar dahil olmak üzere bir tablodaki her sütunu getirir. Veritabanı şemaları geliştikçe ve yeni sütunlar eklendiğinde (şifreler veya PII gibi hassas veriler dahil), SELECT * kullanan sorgular kod değişikliği gerektirmeden bunları otomatik olarak almaya başlar. Bu durum güvenlik açıklarına yol açar ve uygulama mantığınızdaki kabulleri bozar.

Neden önemli?

Performans etkisi: Gereksiz sütunları almak sorgu yürütme süresini, ağ aktarım boyutunu ve bellek tüketimini artırır. Yalnızca 5 sütuna ihtiyacınız varken 50 sütunlu bir tablo kullanmak, gerekenden 10 kat daha fazla veri aktardığınız anlamına gelir; bu da yanıt sürelerini düşürür ve altyapı maliyetlerini artırır.

Güvenlik etkileri: Tablolara eklenen yeni sütunlar (denetim alanları, dahili bayraklar, hassas kullanıcı verileri), SELECT * sorguları aracılığıyla otomatik olarak dışarı açılır. API'niz asla bu uç nokta (endpoint) için tasarlanmamış parola hash'lerini, TC kimlik numaralarını veya dahili iş verilerini sızdırmaya başlayabilir.

Kod sürdürülebilirliği: Şema değişikliklerinden sonra SELECT * sorguları bozulduğunda, hata derleme zamanında değil çalışma zamanında (runtime) gerçekleşir. Boş bırakılamayan (non-nullable) yeni bir sütun veya yeniden adlandırılmış bir alan üretim hatalarına neden olur. Açık sütun listeleri bağımlılıkları netleştirir ve şemalar uyumsuz şekilde değiştiğinde derlemeyi kesintiye uğratır.

Kod örnekleri

❌ Kural dışı:

async function getUserProfile(userId) {
    const query = 'SELECT * FROM users WHERE id = ?';
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Neden yanlıştır?: Bu ifade; password_hash, ssn, internal_notes veya deleted_at gibi potansiyel olarak hassas alanlar dahil tüm sütunları getirir. Şema büyüdükçe bu sorgu yavaşlar ve daha fazla veri açığa çıkarır, oysa uygulama yalnızca üç alan kullanmaktadır.

✅ Kurallara uygun:

async function getUserProfile(userId) {
    const query = `
        SELECT name, email, created_at
        FROM users
        WHERE id = ?
    `;
    const [user] = await db.execute(query, [userId]);

    return {
        name: user.name,
        email: user.email,
        createdAt: user.created_at
    };
}

Sonuç

SQL sorgularında her zaman açık sütun listeleri belirtin. Bu, veri sızıntılarını önler, performansı artırır ve kod ile şema arasındaki bağımlılıkları netleştirir. Sütun adlarını yazmanın küçük ön maliyeti, tüm güvenlik ve performans sorunları sınıfının önüne geçer.

Sık Sorulan Sorular

Sorularınız mı var?

SELECT * ne zaman kabul edilebilir?

Yalnızca geliştirme veya hata ayıklama (debugging) sırasında yapılan geçici sorgularda kabul edilebilir, üretim kodunda asla kullanılmamalıdır. Gerçekten tüm sütunlara ihtiyaç duyduğunuz veri taşıma (migration) komut dosyaları veya tek seferlik raporlar için SELECT * mantıklıdır. Uygulama kodu için, şu anda tüm sütunlara ihtiyacınız olsa bile her zaman açık sütun listeleri kullanın, çünkü şema değişiklikleri kaçınılmazdır.

SELECT * sorguları oluşturan ORM'ler hakkında ne düşünülmeli?

Configure your ORM to select specific fields. Most ORMs (Sequelize, TypeORM, Prisma, SQLAlchemy) support field selection: User.findOne({ attributes: ['name', 'email'] }) or prisma.user.findUnique({ select: { name: true, email: true } }). Always use these options to control what data is retrieved.

SELECT * veritabanı performansını önemli ölçüde etkiler mi?

Evet, özellikle geniş tablolarda bu durum daha belirgindir. Veritabanları diskten daha fazla sayfa okumak zorunda kalır, indeksler o kadar verimli kullanılamaz ve sorgu sonuç kümeleri veritabanı arabellek havuzunda (buffer pool) daha fazla bellek tüketir. Ağ aktarım süresi veri boyutuyla orantılı olarak artar. TEXT veya BLOB sütunları içeren tablolarda bu etkinin boyutu oldukça büyük olabilir.

Çoğu sütuna ihtiyaç duyduğum sorguları nasıl ele almalıyım?

Sütunları açıkça listeleyin. Sütun listesini oluşturmak için IDE'nizin otomatik tamamlama özelliğini kullanın veya information_schema üzerinde sorgu çalıştırın. Bazı ekipler, her kullanım senaryosu için gereken tam sütunları tanımlayan view nesneleri oluşturur veya veritabanı view'ları kullanır. Açık listelerin sunduğu netlik ve güvenlik, yarattığı küçük zahmete fazlasıyla değer.

Kod tabanımda SELECT * kullanımını nasıl tespit edebilirim?

Kod tabanınızda SELECT * desenini (büyük/küçük harf duyarsız olarak) arayın. Birçok statik analiz aracı ve veritabanı sorgu analizörü bu durumu işaretleyebilir. Kod incelemeleri (code review) sırasında, uygulama kodunda SELECT * içeren herhangi bir PR'ı reddedin. Bazı ekipler bu desenleri otomatik olarak tespit edip engellemek için pre-commit hook'ları veya CI kontrolleri kullanır.

Şimdi güvenliğinizi sağlayın

Kodunuzu, bulutunuzu ve çalışma zamanınızı tek bir merkezi sistemde güvenceye alın.
Güvenlik açıklarını otomatik olarak hızla bulun ve düzeltin.

Kredi kartı gerekmez | Tarama sonuçları 32 saniyede.