· kaynak dev.to (home feed)
Sunucu tarafında paywall olmayan ve ücretli kullanıcılardan gizlenen ücretli yapay zeka özelliği
Bir dev.to yazısı, yalnızca istemci tarafındaki kredi kontrolüyle korunan ücretli bir yapay zeka analiz özelliğini anlatıyor: kimlik doğrulaması olmadan yapılan API çağrıları gerçek Gemini isteklerini ücretsiz çalıştırırken, ücretli kullanıcılar özelliği arayüzde bulamıyordu.

Bir geliştirici, her iki yönde de aynı anda başarısız olan ücretli bir yapay zeka özelliğini yayınladığını anlattı: doğru istek yapısını bilen herkes ödemeden kullanabilirken, özelliğin kendisi için yapıldığı aboneler bunu arayüzde hiç bulamıyordu. dev.to'da yayımlanan bu anlatım, yapay zekayı kullanarak varsayımsal "kim kazanırdı" karşılaşmalarını sonuçlandıran APEX Versus adlı siteyle ilgili.
Sitedeki Deep Analysis ve Advanced Analysis seçenekleri her çalıştırma için birkaç kredi ücretlendiriyor ve Pro planda sınırsız olması gerekiyor. Arka planda Google'ın Gemini modeline gerçek çağrılar yapılıyor; bu da her yetkisiz kullanımın, karşılığında gelir olmadan ücretli API kotasını tükettiği anlamına geliyor.
Yalnızca tarayıcıda var olan bir paywall
Gönderiye göre kredi kontrolü tamamen frontend'de bulunuyordu. Gelişmiş karşılaştırmayı asıl yapan API route'u hiçbir şey doğrulamıyordu: kimlik doğrulama başlığı olmadan gönderilen, gelişmiş modu belirten bir POST isteği gerçek bir Gemini çağrısını tetikleyip tam çıktıyı döndürüyordu. Bu route'ta giriş zorunluluğu, kredi kontrolü veya günlük limit yoktu.
Geliştirici bu açığı düz bir curl isteğiyle doğruladı ve var olan rate limiting'in bunun yerine temel karşılaştırma endpoint'ine bağlı olduğunu belirtti — yani koruma, gelişmiş modu isteyen saldırganların hiç dokunması gerekmeyen bir route'a yerleştirilmişti.
Ücretli kullanıcıların göremediği bir özellik
İkinci hata arayüzdeydi. Bir satır JavaScript, izleyici ücretli bir plandaysa Deep Analysis kartını gizliyordu — görünürlük koşulu ters çevrilmişti. Ayrıca Pro kullanıcıları için tasarlanan Advanced Analysis düğmesine hiçbir yerde click handler bağlı değildi; arkasındaki fonksiyon varlığını sürdürüyordu ama onu çağıran hiçbir şey yoktu ve yazıldığı günden beri ölü kod olarak kalıyordu.
Birleşik etki, çalışan bir paywall'ın tam tersiydi: doğru isteği oluşturan ödemeyen kullanıcılar daha derin analizi süresiz ve ücretsiz alırken, ödeme yapan müşteriler finanse ettikleri şeye ulaşmanın görünür bir yoluna sahip değildi.
Her iki belirtinin ardındaki tek kök neden
Gönderi her iki başarısızlığı da tek bir gözden kaçırmaya bağlıyor. Geliştirici daha önce Firestore güvenlik kurallarını sıkılaştırmış, böylece kredi bakiyeleri yalnızca admin SDK kullanan sunucu kodundan yazılabilir hale gelmişti — istemcilerin kendi bakiyesini düzenlemesinin önünü kapatan doğru bir hamleydi bu. Ancak ücretli bir işlemden sonra kredi düşüren eski tarayıcı tarafı kod hiç kaldırılmadı ya da değiştirilmedi. Çalışmaya devam etti, başarısız olmaya devam etti ve hata yönetimi boş bir catch bloğundan oluştuğu için reddedilen bir yazım, başarılı bir yazımdan farklı görünmüyordu. Log yok, hata yok, kimseye sinyal yok.
Gerçeklikle test edilen düzeltme
Teşhis konulduktan sonra çözüm doğrudandı. Kredi kontrolü ve düşümü tamamen sunucu tarafına, Gemini çağrısından önce çalışan bir Firestore transaction'ına taşındı. Ölü istemci tarafı düşüm fonksiyonu silindi, görünürlük koşulu düzeltildi ve eksik düğme sonunda eklendi.
Doğrulama diff'e güvenmek yerine canlı bir ücretli hesapla yapıldı: geliştirici bir Deep Analysis çalıştırdı ve bakiyenin tam olarak iki kredi düştüğünü, atomik ve sunucu onaylı şekilde izledi — gönderinin belirttiğine göre bu, özelliğin var olduğu süredeki ilk başarılı düşümdü.
Neden önemli
Temel gözlem tek bir yan projeden çok daha öteye genellenebilir: istemcide yapılan bir kontrol ile sunucuda yapılan bir kontrol, aynı değişkeni okusalar bile birbirinin yerine geçemez. Tarayıcı tarafındaki sürüm tavsiye niteliğindedir; kararlı bir kullanıcının aşamayacağı tek sürüm sunucu tarafındaki olandır. Gelire dokunan her şey için — krediler, kotalar, yetkilendirmeler — yaptırım backend'e aittir, ideal olarak pahalı model çağrısından önce çalışan ve harcama gerçekleştikten sonra mutabakat yapan değil bir transaction içinde.
Buradaki başarısızlık modları yapısı gereği sessizdi: bir yanda yutulan exception'lar, diğer yonda gizli arayüz öğeleri. Olağan kullanım, rutin test ve kod incelemesi bunların hiçbirini yakalayamadı; sorunu yalnızca kasıtlı bir kod tabanı denetimi ortaya çıkardı. Yazarın kredi veya paywall sistemi işleten herkese verdiği pratik tavsiye, bir bakiyenin kontrol edildiği her yeri aramak ve şu soruyu sormaktır: kullanıcı arayüzü tamamen atlayıp istekleri doğrudan endpoint'e gönderse bu kontrol yine de geçerli olur mu? Yanıt garantiye değil varsayıma dayanıyorsa, ortada bir yaptırım yoktur — yalnızca onun görünümü vardır.
- #api-security
- #paywall
- #gemini
- #firebase
- #server-side