FixVibe

// docs / security guides / hardening

كيفية تأمين تطبيق مبني بأدوات الترميز بالذكاء الاصطناعي

دليل تقوية خطوة بخطوة للتطبيقات التي أنشأتها باستخدام Cursor أو Claude Code أو Lovable أو Bolt أو v0 أو Replit أو Windsurf. أربع مراحل: فهم سبب فشل التطبيقات التي تم إنشاؤها AI- بشكل مختلف، وإجراء تدقيق فوري لقاعدة التعليمات البرمجية، والتشدد في وقت النشر، ثم مواصلة المراقبة. رأي، سردي، مع مقتطفات حقيقية يمكنك نسخها.

لماذا تفشل التطبيقات التي تم إنشاؤها AI- بشكل مختلف

يمكن أن تكون التطبيقات المشفرة بـ Vibe آمنة. إنهم بحاجة إلى تصريح تدقيق إضافي لأن أوضاع الفشل هيكلية وليست مهملة:

  • Cursor inlines hardcoded keys. أنت تطلب من Cursor "إصلاح خطأ المصادقة"، وتقوم بلصق مثال Supabase الذي يفترض عميل دور الخدمة. ينتهي المفتاح في أعلى مكون الصفحة. يتواجد كل من العميل المجهول وعميل الخدمة معًا؛ كلا السفينة.
  • Claude Code defaults to permissive CORS. يتم شحن معالجات Generated Express / Fastify مع cors({ origin: '*' }) لأن هذه هي أسرع طريقة للحصول على معاينة عملية. لا تحصل البرامج الوسيطة على تمريرة ثانية أبدًا.
  • Lovable and v0 skip the rules file. تنشئ المشاريع المدعومة من Firestore نموذج البيانات ولكن نادرًا ما تلمس firestore.rules. تنتهي صلاحية قواعد وضع الاختبار بصمت ويتم قفل قاعدة البيانات دون أي تحذير للمستخدم.
  • Bolt skips RLS migrations. Bolt ينشئ مخططًا Supabase وسطحًا CRUD يستخدم المفتاح المجهول. ENABLE ROW LEVEL SECURITY لا يدخل في عملية الترحيل مطلقًا. يمكن للمستخدمين المجهولين قراءة أو كتابة أي صف.
  • Windsurf trusts unsigned IDs. الذي تم إنشاؤه GET /api/items/[id] يقرأ المعلمة ويستعلم عن Postgres دون التحقق من الملكية. النمط شائع بدرجة كافية بحيث يظهره المسبار النشط active.idor-walking خلال عملية مسح واحدة.

التدقيق الفوري: grep قاعدة التعليمات البرمجية الخاصة بك لأنماط المخاطر

قبل أن تصلب أي شيء، ابحث عن ما تم كسره بالفعل. تستغرق كل هذه الخطوات أقل من دقيقة:

الأسرار ومفاتيح المزود

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

أي ضربة تحتاج إلى الحذف بالإضافة إلى تدوير المفتاح. لوحات معلومات Provider: Supabase → الإعدادات → API، Stripe → المطورون → API المفاتيح، وحدة تحكم Anthropic / OpenAI.

ضوابط الوصول إلى قاعدة البيانات

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

يحتاج كل CREATE TABLE public.* إلى مطابقة ENABLE ROW LEVEL SECURITY وسياسة واحدة على الأقل. يجب أن تحدد قواعد Firestore نطاق القراءة إلى request.auth.uid.

المصادقة والتعامل مع الجلسة

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/

يجب أن تستخدم المسارات التي يعرضها الخادم supabase.auth.getUser() — ويتم التحقق منها باستخدام الواجهة الخلفية. getSession() يقرأ ملف تعريف الارتباط الذي لم يتم التحقق منه. يمكن الوصول إلى الرموز المميزة الموجودة في localStorage بواسطة أي برنامج نصي يتم تشغيله على الصفحة.

الرؤوس والبرمجيات الوسيطة

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/، يتم التقاط src/middleware.ts فقط. إذا كان ملف البرنامج الوسيط الخاص بك موجودًا في جذر المشروع، فإن Next.js يتجاهله بصمت ولن يعمل منطق تحديث المصادقة / CSP أبدًا.

تصلب في وقت النشر

بمجرد تنظيف المصدر، قم بتأمين كيفية وصول التطبيق إلى مرحلة الإنتاج.

الخطوة 1: بيئات منفصلة

Vercel: ثلاث بيئات - Production (مجال الإنتاج الخاص بك)، المعاينة (PR / النشر المرحلي)، التطوير (محلي). يحصل كل منها على مجموعة env-var الخاصة به. المفاتيح المباشرة Stripe / الأنثروبي / Supabase لا تصل أبدًا إلى المعاينة؛ لا تصل مفاتيح المعاينة أبدًا إلى Production. تدفع الفروع للمعاينة تلقائيًا؛ دمج إلى main نشر إلى Production.

الخطوة 2: صارمة CSP عبر البرامج الوسيطة

أنشئ رقمًا لكل طلب، ثم أدخله في Content-Security-Policy. Next.js يطبق الرقم تلقائيًا على علامات البرنامج النصي الخاصة به عندما تقوم بتعيين رأس الطلب x-nonce.

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: فرض RLS على كل طاولة عامة

RLS لا يتم تمكينه افتراضيًا ولا يتم فرضه على مالكي الجدول إلا إذا قمت FORCE بذلك. قم بإقران كل جدول بسياسات واضحة لكل دور.

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);

الخطوة 4: التحقق من مصادقة الخادم فقط على كل مسار API

يتحقق كل مسار API لتغيير الحالة من جانب خادم المتصل باستخدام supabase.auth.getUser(). يصبح كائن المستخدم مصدر الحقيقة لـ user_id — لا تثق أبدًا في نص الطلب لتعيينه.

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: عكس تحليلاتك

Proxying التحليلات من خلال المجال الخاص بك تتجنب أدوات حظر الإعلانات وتسمح لـ CSP connect-src 'self' بالبقاء محدودًا. يعمل نفس النمط مع PostHog وPlusible وUmami وأحواض الأحداث المخصصة.

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(),
  });
}

الخطوة 6: حماية إعادة التوجيه المفتوحة على ارتداد ما بعد المصادقة

عادةً ما تقبل تدفقات تسجيل الدخول/التسجيل معلمة استعلام next. ارفض أي شيء ليس مسارًا لنفس الموقع — ابدأ بـ / ولا // أبدًا (نسبي للبروتوكول، يرسل المستخدمين خارج الموقع).

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

مستمر: المراقبة وإعادة المسح

يحدث الانجراف عند كل عملية نشر. تعامل مع الأمان كحلقة، وليس قائمة مرجعية تنتهي منها.

تحقق من مجال الإنتاج الخاص بك

Dashboard → Domains → أضف مجال المنتج الخاص بك → DNS TXT أو HTTP- التحقق من الملف (خطوة واحدة). بمجرد التحقق، تصبح عمليات الفحص النشطة متاحة ويمكن تمكين عمليات إعادة الفحص المجدولة.

جدولة عمليات إعادة الفحص السلبية

يوميًا على Hobby، كل 3 ساعات على Pro، كل ساعة على Unlimited. تقوم كل عملية تشغيل بإرسال بريد إلكتروني إليك في حالة ظهور نتيجة جديدة، ويتم تشغيل خطاف ويب scan.completed إذا قمت بالاشتراك.

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- عمليات الفحص النشطة (اختياري)

إذا كنت تريد فحصًا نشطًا آليًا (SQLi / XSS / IDOR المشي / وما إلى ذلك)، فقم بتشغيله لكل مجال في Dashboard → Domains → API active. التفويض دائم، وتنتهي مدته 90 يومًا، وقابل للإلغاء على الفور. قم بالاقتران مع خطاف الويب scan.active_api.first_used حتى يصل أول فحص نشط آلي بعد التمكين إلى تنبيهك.

قم بتوصيل النتائج إلى سير العمل AI الخاص بك

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.

كشف التهديدات المباشرة (Unlimited)

تظهر اختلافات سجل شفافية الشهادات شهادات TLS الجديدة الصادرة لنطاقك. DNS- تكتشف اختلافات السجل التغييرات غير المصرح بها. JS- يتم تشغيل المراقبة السرية للحزمة في اللحظة التي يصل فيها المفتاح الجديد إلى الحزمة المشحونة. تقوم خلاصات Threat-intel (Spamhaus، URLhaus) بالإبلاغ عن المجال الخاص بك إذا كان مدرجًا.

أنماط الفشل الحقيقية وإصلاحاتها

خمسة أنماط من عمليات فحص الإنتاج عبر الآلاف من التطبيقات AI- التي تم إنشاؤها، كل منها يحتوي على الإصلاح الفعلي:

  1. مفتاح دور الخدمة في مكون العميل

    Symptom: baas.supabase-service-key العثور على الإنتاج URL. Cause: تم لصق Cursor الإكمال التلقائي createClient(URL, SERVICE_ROLE_KEY) في مكون React. Fix: انقل عميل الخدمة إلى src/lib/supabase/service.ts مع وجود import 'server-only' في الأعلى؛ إنشاء src/lib/supabase/client.ts موازٍ باستخدام المفتاح المجهول للاستخدام من جانب العميل؛ قم بتدوير مفتاح دور الخدمة عبر Supabase Studio.

  2. تركت قواعد Firestore في وضع الاختبار

    Symptom: baas.firebase-rules اكتشاف عالي الخطورة. Cause: قراءة القواعد التي تم إنشاؤها allow read, write: if request.time < timestamp.date(2026, 6, 1); - "السماح للجميع" محدد بالوقت. Fix: نطاق كل قاعدة للمستخدم المصادق عليه - match /users/{userId}/posts/{postId} { allow read, write: if request.auth.uid == userId; } - وأعد النشر firebase deploy --only firestore:rules.

  3. مسموح CORS بالبقاء في مرحلة الإنتاج

    Symptom: active.cors شديدة الخطورة. Cause: تم إنشاء برنامج وسيط سريع: app.use(cors({ origin: '*' })). Fix: القائمة المسموح بها لأصل الواجهة الأمامية: app.use(cors({ origin: ['https://your-app.com'], credentials: true })). بالنسبة للمسارات Next.js API، قم بتعيين Access-Control-Allow-Origin بشكل صريح في الاستجابة.

  4. RLS ممكّن ولكن ليس قسريًا

    Symptom: نشط baas.supabase-rls يُبلغ عن إمكانية كتابة الدور المجهول في جدول عام على الرغم من تمكين RLS في لوحة المعلومات. Cause: ENABLE بدون FORCE يترك مالك الجدول معفيًا - ويتم تشغيل عمليات الترحيل كمالك. Fix: قم بإلحاق alter table public.items force row level security; بالترحيل. إعادة النشر.

  5. معرفات غير موقعة IDOR- قابلة للمشي

    Symptom: active.idor-walking تقارير يمكن للمستخدم المجهول قراءة /api/items/1، /api/items/2، ... عبر المستأجرين. Cause: يثق المعالج API بمعلمة المسار ويستعلم عن Postgres بدون مسند ملكية. Fix: أضف .eq('user_id', user.id) في كل استعلام قراءة، أو انتقل إلى عناوين URL الموقعة / UUIDs المحددة ضمن /api/users/[uid]/items/[id].

حلقة الأمان ذات الرمز الحيوي

الهدف ليس الأمن المثالي؛ إنها تقضي على الثمار المنخفضة التي تفتقدها الأدوات AI باستمرار حتى تتمكن من الاستمرار في الشحن بسرعة.

  1. Generate fast - ​​استخدم Cursor، Claude Code، Lovable، Bolt. هذه هي النقطة.
  2. Audit immediately - ​​قم بتشغيل مجموعة grep أعلاه، وتحقق من RLS، وتحقق من CSP، وراجع حدود المصادقة.
  3. Harden at deploy - ​​البرامج الوسيطة، فصل البيئة، CSP nonce، HSTS، التحقق من مصادقة الخادم فقط.
  4. Monitor — FixVibe سلبي يوميًا، ونشط أسبوعيًا على نطاق تم التحقق منه، وخطافات الويب إلى Slack، واكتشاف التهديدات على Unlimited.
  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.

الخطوات التالية

للحصول على الخلفية المفاهيمية لـ DAST مقابل SAST ولماذا تحتاج التطبيقات التي تم إنشاؤها AI- إلى المسح الضوئي الخاص بها، اقرأ AI-generated code security scanning. للحصول على مرجع سريع لمراجعة ما قبل الشحن، راجع vibe coding security checklist.

// scan your app

كفّ عن القراءة. ابدأ بإيجاد الثغرات في تطبيقك.

أدخل URL — FixVibe يُجري كل فحص سلبي من هذا الدليل بالإضافة إلى أكثر من 200 فحص آخر في أقل من دقيقة. Free، بدون تثبيت، بدون بطاقة.

  • Free الطبقة — 3 عمليات مسح/شهر، بدون بطاقة.
  • عمليات الفحص السلبي ضد أي URL — لا حاجة للتحقق من المجال.
  • تم ضبطه على Cursor، Claude Code، Lovable، Bolt، v0، Replit.
  • Coding-agent prompts for code/config findings, plus operator steps for DNS/provider fixes.
كيفية تأمين تطبيق مبني بأدوات الترميز بالذكاء الاصطناعي — Docs · FixVibe