FixVibe

// docs / security guides / hardening

AI kodlama araçlarıyla yapılmış bir uygulamayı nasıl güvenli hale getirirsiniz

Cursor, Claude Code, Lovable, Bolt, v0, Replit veya Windsurf ile oluşturduğunuz uygulamalar için adım adım sağlamlaştırma kılavuzu. Dört aşama: AI-oluşturulan uygulamaların neden farklı şekilde başarısız olduğunu anlayın, anında bir kod tabanı denetimi çalıştırın, dağıtım zamanında sağlamlaştırın ve ardından izlemeye devam edin. Fikir odaklı, anlatımlı, gerçek parçalarla kopyalayabilirsiniz.

AI-oluşturulan uygulamalar neden farklı şekilde başarısız oluyor?

Vibe kodlu uygulamalar güvenli olabilir. Arıza modları dikkatsiz değil yapısal olduğu için fazladan bir denetim geçişine ihtiyaçları var:

  • Cursor inlines hardcoded keys. Cursor'den "kimlik doğrulama hatasını düzeltmesini" istersiniz ve o, hizmet rolü istemcisi olduğunu varsayan bir Supabase örneğini yapıştırır. Anahtar, sayfa bileşeninin en üstünde sona erer. Hem anon istemcisi hem de hizmet istemcisi bir arada bulunur; ikisi de gemi.
  • Claude Code defaults to permissive CORS. Generate Express / Fastify işleyicileri cors({ origin: '*' }) ile birlikte gönderilir çünkü bu, çalışma önizlemesi almanın en hızlı yoludur. Ara yazılım asla ikinci bir geçişe sahip olamaz.
  • Lovable and v0 skip the rules file. Firestore destekli projeler veri modelini oluşturur ancak nadiren firestore.rules'ye dokunur. Test modu kuralları sessizce sona erer ve kullanıcıya hiçbir uyarı vermeden veritabanını kilitler.
  • Bolt skips RLS migrations. Bolt bir Supabase şeması ve anon anahtarını kullanan bir CRUD yüzeyi oluşturur. ENABLE ROW LEVEL SECURITY hiçbir zaman geçişe girmez. Anonim kullanıcılar herhangi bir satırı okuyabilir veya yazabilir.
  • Windsurf trusts unsigned IDs. Oluşturulan GET /api/items/[id], parametreyi okur ve mülkiyeti doğrulamadan Postgres'i sorgular. Desen, aktif active.idor-walking probunun onu tek bir taramada yüzeye çıkarmasını sağlayacak kadar yaygındır.

Acil denetim: risk kalıpları için kod tabanınızı gravürleyin

Herhangi bir şeyi sertleştirmeden önce zaten kırılmış olanı bulun. Bu greplerin her biri bir dakikadan az sürüyor:

Sırlar ve sağlayıcı anahtarları

bash
grep -RIn 'NEXT_PUBLIC_SUPABASE_SERVICE' src/
grep -RIn 'sk_live_\|pk_live_\|STRIPE_SECRET' src/
grep -RIn 'sk-ant-\|^sk-' src/  # Anthropic / OpenAI
grep -RIn 'AIza\|AKIA' src/        # Google / AWS
grep -RIn 'eyJh[A-Za-z0-9_-]\{20,\}' src/  # JWT-shaped strings

Herhangi bir vuruşun silinmesi ve anahtar döndürmesi gerekir. Provider kontrol panelleri: Supabase → Ayarlar → API, Stripe → Geliştiriciler → API tuşları, Antropik / OpenAI konsolu.

Veritabanı erişim kontrolleri

bash
# Supabase migrations
grep -RIn 'CREATE TABLE public\.' supabase/migrations/
grep -RIn 'ENABLE ROW LEVEL SECURITY\|FORCE ROW LEVEL SECURITY' supabase/migrations/

# Firebase / Firestore
cat firestore.rules  # confirm no `if true;` matches

Her CREATE TABLE public.*'nin eşleşen bir ENABLE ROW LEVEL SECURITY ve en az bir politikaya ihtiyacı vardır. Firestore kuralları, okumaları request.auth.uid kapsamına almalıdır.

Kimlik doğrulama ve oturum yönetimi

bash
grep -RIn 'getSession()' src/   # should be getUser() server-side
grep -RIn 'localStorage\.\(set\|get\)Item.*token' src/
grep -RIn 'jwt.verify.*\(noVerify\|skipVerify\)' src/

Sunucu tarafından oluşturulan rotalar supabase.auth.getUser() kullanmalıdır; arka uçla doğrulanır. getSession() doğrulanmamış bir çerezi okur. localStorage içindeki belirteçlere sayfada çalışan herhangi bir komut dosyası tarafından erişilebilir.

Başlıklar ve ara yazılım

bash
# Confirm middleware location for src/ layouts
ls src/middleware.ts middleware.ts 2>&1

# Look for CSP and security headers
grep -RIn 'Content-Security-Policy\|Strict-Transport-Security' src/

src/ düzeniyle yalnızca src/middleware.ts seçilir. Ara yazılım dosyanız proje kökündeyse, Next.js onu sessizce yok sayar ve CSP / auth-refresh mantığınız hiçbir zaman çalışmaz.

Dağıtım zamanında sertleşme

Kaynak temizlendikten sonra uygulamanın üretime ulaşma şeklini kilitleyin.

1. Adım: Ortamları ayırın

Vercel: üç ortam — Production (üretim alanınız), Önizleme (PR / hazırlama dağıtımları), Geliştirme (yerel). Her biri kendi env-var setini alır. Canlı Stripe / Antropik / Supabase tuşları hiçbir zaman Önizlemeye ulaşmaz; Önizleme tuşları hiçbir zaman Production'a ulaşmaz. Dallar otomatik olarak Önizleme'ye geçer; main ile birleştirme, Production'a dağıtılır.

Adım 2: Ara katman yazılımı aracılığıyla CSP katı kuralları

İstek başına bir kez oluşturun ve bunu Content-Security-Policy içine enjekte edin. Next.js, x-nonce istek başlığını ayarladığınızda nonce'ı kendi komut dosyası etiketlerine otomatik olarak uygular.

ts
// src/middleware.ts
import { NextResponse, type NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const nonce = crypto.randomUUID().replace(/-/g, '');
  const csp = [
    `script-src 'nonce-${nonce}' 'strict-dynamic'`,
    `style-src 'self' 'unsafe-inline'`,
    `img-src 'self' data: https:`,
    `connect-src 'self' https://*.supabase.co`,
    `object-src 'none'`,
    `base-uri 'self'`,
    `frame-ancestors 'none'`,
  ].join('; ');

  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-nonce', nonce);

  const response = NextResponse.next({ request: { headers: requestHeaders } });
  response.headers.set('Content-Security-Policy', csp);
  response.headers.set('X-Content-Type-Options', 'nosniff');
  response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  return response;
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

3. Adım: Her genel masada RLS'ı zorunlu kılın

RLS varsayılan olarak etkin değildir ve FORCE kullanmadığınız sürece tablo sahipleri için zorunlu kılınmaz. Her tabloyu, rol başına açık politikalarla eşleştirin.

sql
-- supabase/migrations/XXXX_rls.sql
alter table public.profiles enable row level security;
alter table public.profiles force row level security;

create policy "profiles: read own"
  on public.profiles for select
  using (auth.uid() = id);

create policy "profiles: update own"
  on public.profiles for update
  using (auth.uid() = id)
  with check (auth.uid() = id);

Adım 4: Her API rotasında yalnızca sunucu kimlik doğrulaması

Durum değiştiren her API rotası, arayan sunucu tarafını supabase.auth.getUser() ile doğrular. Kullanıcı nesnesi user_id için gerçeğin kaynağı haline gelir; onu ayarlamak için asla bir istek gövdesine güvenmeyin.

ts
// src/app/api/items/route.ts
import { NextResponse, type NextRequest } from 'next/server';
import { createClient } from '@/lib/supabase/server';

export async function POST(request: NextRequest) {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) return NextResponse.json({ error: 'unauthorized' }, { status: 401 });

  const body = await request.json();
  const { data, error } = await supabase
    .from('items')
    .insert({ ...body, user_id: user.id })  // server-supplied, not from body
    .select()
    .single();

  if (error) return NextResponse.json({ error: error.message }, { status: 400 });
  return NextResponse.json(data);
}

5. Adım: Analitiklerinizi ters proxy ile temsil edin

Proxy analitiğini kendi alanınız üzerinden yapmak, reklam engelleyicileri önler ve CSP connect-src 'self' alanınızın dar kalmasını sağlar. Aynı model PostHog, Plausible, Umami, özel olay havuzları için de geçerlidir.

ts
// src/app/api/posthog/[...path]/route.ts
import { type NextRequest } from 'next/server';

const UPSTREAM = 'https://us.i.posthog.com';

export async function POST(req: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
  const { path } = await params;
  const url = `${UPSTREAM}/${path.join('/')}`;
  return fetch(url, {
    method: 'POST',
    headers: { 'content-type': req.headers.get('content-type') ?? 'application/json' },
    body: await req.text(),
  });
}

Adım 6: Kimlik doğrulama sonrası geri dönüşte açık yönlendirme koruması

Oturum açma/kaydolma akışları genellikle next sorgu parametresini kabul eder. Aynı site yolu olmayan her şeyi reddedin; / ile başlayın ve asla // (protokole bağlı, kullanıcıları site dışına gönderir) ile başlayın.

ts
function safeNext(raw: string | null): string {
  if (!raw) return '/dashboard';
  if (!raw.startsWith('/') || raw.startsWith('//')) return '/dashboard';
  return raw;
}

Devam ediyor: izleme ve yeniden tarama

Drift her konuşlandırmada gerçekleşir. Güvenliği, tamamladığınız bir kontrol listesi olarak değil, bir döngü olarak ele alın.

Üretim alanınızı doğrulayın

Dashboard → Domains → ürün alan adınızı ekleyin → DNS TXT veya HTTP-dosya doğrulaması (tek adımlı). Doğrulandıktan sonra aktif taramalar kullanılabilir hale gelir ve planlanmış yeniden taramalar etkinleştirilebilir.

Pasif yeniden taramaları zamanlayın

Her gün Hobby'de, 3 saatte bir Pro'de, saatte bir Unlimited'de. Her çalıştırmada yeni bir bulgu ortaya çıkarsa size e-posta gönderilir ve abone olduysanız bir scan.completed web kancası tetiklenir.

bash
# Or from CI, via the REST API:
curl -X POST https://fixvibe.app/api/v1/scans \
  -H "authorization: Bearer $FIXVIBE_TOKEN" \
  -H "content-type: application/json" \
  -d '{"target":"https://your-app.com"}'

API-aktif taramaları etkinleştirin (isteğe bağlı)

Otomatik etkin tarama (SQLi / XSS / IDOR yürüme / vb.) istiyorsanız, Kontrol Paneli → Etki Alanları → API etkin bölümünden bunu etki alanı başına açın. Yetkilendirme kalıcıdır, süresi 90 gündür ve anında iptal edilebilir. Etkinleştirmeden sonraki ilk otomatik aktif taramanın uyarınıza ulaşması için scan.active_api.first_used web kancasıyla eşleştirin.

Bulguları AI iş akışınıza bağlayın

Mint an API token at Account → API tokens, then configure the MCP server (/docs/mcp) in Claude Desktop / Cursor / Continue. Ask your agent: "Run a scan on staging and show me the highest-severity findings." The agent calls FixVibe, fetches the report, and renders categorized remediation guidance so code/config fixes become prompts and DNS/provider/manual fixes become operator steps.

Canlı tehdit tespiti (Unlimited)

Sertifika şeffaflığı günlüğü farklılıkları, alanınız için verilen yeni TLS sertifikalarını ortaya çıkarır. DNS-kayıt farkları yetkisiz değişiklikleri yakalar. JS-paket gizli izleme, yeni bir anahtarın gönderilen pakete ulaştığı anda devreye girer. Tehdit istihbaratı beslemeleri (Spamhaus, URLhaus) listeleniyorsa alan adınızı bildirin.

Gerçek arıza modelleri ve bunların düzeltmeleri

Binlerce AI- oluşturulan uygulamadaki üretim taramasından elde edilen beş model, her biri gerçek düzeltmeyi içeriyor:

  1. İstemci bileşenindeki hizmet rolü anahtarı

    Symptom: baas.supabase-service-key üretimde URL bulma. Cause: Cursor otomatik tamamlama, createClient(URL, SERVICE_ROLE_KEY)'yi bir React bileşenine yapıştırdı. Fix: hizmet istemcisini en üstte import 'server-only' olacak şekilde src/lib/supabase/service.ts konumuna taşıyın; istemci tarafında kullanım için anon anahtarını kullanarak paralel bir src/lib/supabase/client.ts oluşturun; Supabase Studio aracılığıyla hizmet rolü anahtarını döndürün.

  2. Firestore kuralları test modunda kaldı

    Symptom: baas.firebase-rules yüksek önemde bulgu. Cause: oluşturulan kurallar allow read, write: if request.time < timestamp.date(2026, 6, 1); şeklinde okunur - zaman sınırlı bir "tümüne izin ver". Fix: her kuralı kimliği doğrulanmış kullanıcıya (match /users/{userId}/posts/{postId} { allow read, write: if request.auth.uid == userId; }) dahil edin ve firebase deploy --only firestore:rules'yi yeniden konuşlandırın.

  3. Müsamahakar CORS üretime devam ediyor

    Symptom: active.cors yüksek önem. Cause: oluşturulan Express ara yazılımı: app.use(cors({ origin: '*' })). Fix: ön uç kaynağınızı izin verilenler listesine ekleyin: app.use(cors({ origin: ['https://your-app.com'], credentials: true })). Next.js API rotaları için yanıtta Access-Control-Allow-Origin'yi açıkça ayarlayın.

  4. RLS etkin ancak zorunlu değil

    Symptom: etkin baas.supabase-rls, kontrol panelinde RLS etkinleştirilmiş olsa bile anon rolünün genel bir tabloya yazabildiğini bildirir. Cause: ENABLE FORCE olmadan tablo sahibini muaf tutar ve taşıma işlemleri sahip olarak gerçekleştirilir. Fix: taşıma işlemine alter table public.items force row level security; ekleyin. Yeniden konuşlandırın.

  5. İmzasız IDOR-yürünebilir kimlikler

    Symptom: active.idor-walking, anon kullanıcısının kiracılar arasında /api/items/1, /api/items/2, ... okuyabildiğini bildirir. Cause: API işleyicisi yol parametresine güvenir ve Postgres'i sahiplik koşulu olmadan sorgular. Fix: her okuma sorgusuna .eq('user_id', user.id) ekleyin veya /api/users/[uid]/items/[id] kapsamına alınan imzalı URL'lere/UUID'lere gidin.

Vibe kodu güvenlik döngüsü

Amaç mükemmel güvenlik değil; AI araçlarının sürekli olarak gözden kaçırdığı düşük asılı meyveleri ortadan kaldırır, böylece nakliyeyi hızlı bir şekilde sürdürebilirsiniz.

  1. Generate fast — Cursor, Claude Code, Lovable, Bolt kullanın. Önemli olan bu.
  2. Audit immediately — yukarıdaki grep ayarını çalıştırın, RLS'yi işaretleyin, CSP'yi doğrulayın, kimlik doğrulama sınırını inceleyin.
  3. Harden at deploy — ara yazılım, ortam ayırma, CSP tek seferlik, HSTS, yalnızca sunucu kimlik doğrulaması.
  4. Monitor — FixVibe günlük pasif, doğrulanmış bir alanda haftalık olarak aktif, Slack'e yönelik web kancaları, Unlimited üzerinde tehdit algılama.
  5. Fix fast — use FixVibe coding-agent prompts for code/config findings and operator steps for DNS, provider, secret-rotation, or manual-review findings. Re-deploy, re-scan, close the loop.

Sonraki adımlar

DAST ile SAST arasındaki kavramsal arka plan ve AI-oluşturulan uygulamaların neden kendi taramalarına ihtiyaç duyduğu hakkında bilgi edinmek için AI-generated code security scanning bölümünü okuyun. Hızlı referans gönderim öncesi denetimi için vibe coding security checklist adresine bakın.

// scan your app

Okumayı bırak. Kendi uygulamandaki açıkları bulmaya başla.

Bir URL bırakın — FixVibe, bu kılavuzdaki tüm pasif kontrolü ve ayrıca 200'den fazla kişiyi bir dakikadan kısa sürede çalıştırır. Free, yükleme yok, kart yok.

  • Free katman — ayda 3 tarama, kart yok.
  • Herhangi bir URL'ye karşı pasif taramalar — etki alanı doğrulaması gerekmez.
  • Cursor, Claude Code, Lovable, Bolt, v0, Replit için ayarlandı.
  • Coding-agent prompts for code/config findings, plus operator steps for DNS/provider fixes.
AI kodlama araçlarıyla yapılmış bir uygulamayı nasıl güvenli hale getirirsiniz — Docs · FixVibe