Bolt.new وضع مفاتيح الـAPI الخاصة بك في المتصفّح — كيف تُصلح ذلك
إعداد Bolt.new الافتراضي يضع المفاتيح السرّية داخل حزمة العميل حيث يستطيع أيّ شخص قراءتها — إليك كيف تفحص تطبيقك وتنقل كل مفتاح إلى الخادم حيث يجب أن يكون.
إذا أطلقت تطبيقاً باستخدام Bolt.new، فهناك احتمال كبير أن مفاتيح الـAPI الخاصة بك موجودة الآن في المتصفّح، يستطيع قراءتها أيّ شخص يفتح DevTools. هذا ليس خطأً نادراً — إنه السلوك الافتراضي. أدوات البناء بالذكاء الاصطناعي تُحسّن من أجل عرض يعمل، وأسرع طريقة لجعل طلب OpenAI أو دفعة Stripe أو استعلام Supabase يعمل داخل المعاينة هي لصق المفتاح مباشرةً في كود الواجهة. يعمل الكود، ويبدو العرض مثالياً، ويُشحن السرّ إلى كل زائر. وهذا مهمّ لأن الإعدادات غير الآمنة هي القاعدة لا الاستثناء: عبر التطبيقات المبنية بالذكاء الاصطناعي يحمل نحو 91.5% منها عيباً أمنياً واحداً على الأقل، وكشف فحص أجرته Escape.tech على 5,600 تطبيق عن أكثر من 400 سرّ مكشوف. ونمط الفشل المميّز لـBolt هو أحد هذه الأسرار.
لماذا يُسرّب Bolt.new المفاتيح افتراضياً
يولّد Bolt.new تطبيقات تعمل على جهة العميل — عادةً واجهة Vite أو Next.js تعمل داخل متصفّح المستخدم. أيّ شيء في تلك الحزمة عامّ. عادتان تسبّبان التسريب. الأولى أن المفتاح يُثبَّت مباشرةً داخل مكوّن أو داخل استدعاء fetch. والثانية، وهي أكثر خفاءً، أن المفتاح يُخزَّن في متغيّر بيئة يُدمَج داخل بناء العميل. في تطبيق Vite، أيّ متغيّر يبدأ بـVITE_ يُدمَج داخل الـJavaScript المشحون إلى المتصفّح؛ وفي Next.js ينطبق الأمر نفسه على أيّ متغيّر يبدأ بـNEXT_PUBLIC_. وكثيراً ما يسمّي Bolt سرّاً باسم VITE_OPENAI_API_KEY أو NEXT_PUBLIC_STRIPE_SECRET_KEY، وهو ما يبدو كمتغيّر بيئة لكنه في الحقيقة نصّ عامّ. القاعدة بسيطة ومطلقة: إذا كان الكود الذي يقرأ المفتاح يعمل في المتصفّح، فالمفتاح ليس سرّياً، مهما كان الاسم الذي أعطيته للمتغيّر.
كيف تفحص تطبيقك في خمس دقائق
لا تحتاج إلى خلفية أمنية لتكتشف هذا. افتح تطبيقك المنشور في متصفّح، افتح DevTools، وانتقل إلى تبويب Network؛ أعد تحميل الصفحة وانظر إلى ملفّات الـJavaScript التي يجري تنزيلها. استخدم بحث المتصفّح عبر المصادر (في Chrome DevTools اضغط Ctrl+Shift+F / Cmd+Option+F) وابحث عن بداية بادئة مفتاح معروفة — sk- (أو sk-proj-) لمفاتيح OpenAI، وsk_live_ / sk_test_ / rk_live_ لمفاتيح Stripe السرّية، أو AIza لمفاتيح Google، أو رمز service_role الخاص بمشروع Supabase لديك. إذا ظهرت أيّ مطابقة داخل ملفّ نزّله المتصفّح، فذلك المفتاح عامّ. افعل الشيء نفسه في شيفرتك المصدرية: ابحث في المستودع كلّه عن المفتاح الحرفي، وابحث بـgrep عن أسماء المتغيّرات VITE_ وNEXT_PUBLIC_ التي تحمل أيّ شيء تعتبره سرّاً. وعامِل كل مفتاح تجده بهذه الطريقة على أنه مكشوف بالفعل.
- دوّر أولاً: أبطِل المفتاح المكشوف من لوحة تحكّم المزوّد وأصدِر مفتاحاً جديداً — افترض أن القديم قد جُمِع بالفعل
- انقل كل سرّ خارج الواجهة وإلى خادم: مسار API، أو دالة edge، أو خدمة خلفية صغيرة يستدعيها المتصفّح بدلاً من مزوّد الخدمة مباشرةً
- أعد تسمية القيم الآمنة للعميل فقط؛ ولا تضع سرّاً خلف بادئتَي VITE_ أو NEXT_PUBLIC_ أبداً
- أضِف .env إلى .gitignore وتأكّد من أن أيّ مفتاح لم يُرفع من قبل (افحص تاريخ Git لا الملفّات الحالية فحسب)
- اضبط حدوداً للإنفاق وتنبيهات استخدام لكل مفتاح على OpenAI وStripe وأيّ API مدفوع كسقف لنطاق الضرر
- أعد فحص تبويب Network بعد إعادة النشر للتأكّد من أن المفتاح لم يعد يظهر في أيّ ملفّ منزَّل
الإصلاح الحقيقي: ضع السرّ على الخادم
تدوير المفتاح المسرَّب يوقف النزيف، لكن المفتاح الجديد يُسرَّب بالطريقة نفسها ما لم تُغيّر مكان وجوده. الإصلاح الدائم معماريّ: يجب ألّا يقرأ السرّ إلا كودٌ لا يستطيع المستخدم رؤيته. فبدلاً من أن يستدعي المتصفّح OpenAI أو Stripe مباشرةً والمفتاح مرفق، يستدعي المتصفّح نقطة نهاية على خادمك أنت — مسار API في Next.js، أو دالة serverless أو edge، أو Supabase Edge Function — ويحتفظ ذلك الكود على جهة الخادم بالمفتاح، ويُجري الاستدعاء الخارجي، ويعيد النتيجة فقط. يبقى المفتاح في متغيّر بيئة خاصّ بالخادم (بلا بادئة VITE_ أو NEXT_PUBLIC_) لا يُدمَج أبداً في العميل. هذا يمنحك أيضاً مكاناً طبيعياً لإضافة ما تجاهله Bolt: المصادقة على نقطة النهاية، وحدود المعدّل، والتحقق من المدخلات، حتى لا يستطيع غريب تضخيم فاتورة OpenAI لديك حتى بعد إخفاء المفتاح بأمان.
المفتاح في المتصفّح ليس عيباً تُرقّعه مرة واحدة — إنه قرار تصميم اتخذته الأداة نيابةً عنك. وإصلاحه يعني نقل السرّ إلى الخادم، لا إخفاءه على العميل بشكل أفضل.
تحقّق، ثم حافظ على ذلك
بعد أن تنقل كل سرّ إلى الخادم وتعيد النشر، أثبِت ذلك. كرّر فحصَي تبويب Network والبحث في المصدر وتأكّد من أن أيّ بادئة مفتاح لا تظهر في أيّ ملفّ ينزّله المتصفّح. ثم امنع الانتكاس: في كل مرّة تطلب فيها من Bolt ميزة جديدة تمسّ API خارجياً، قد يعيد إدخال مفتاح على جهة العميل، لذا اجعل فحص DevTools جزءاً من روتين الإصدار لديك لا تنظيفاً لمرّة واحدة. النمط متّسق عبر أدوات البناء بالذكاء الاصطناعي — Bolt يُسرّب الأسرار، وCursor يميل إلى شحن تفويض معطوب على مستوى الكائن (BOLA)، وLovable كثيراً ما يُشحن بلا Row-Level Security في Supabase، ونشرات Replit كشفت ملفّات .env — لكنها تتشارك جذراً واحداً: الأداة تُثبت أن الميزة تعمل وتتوقّف عند ذلك، تاركةً الأمن لك.
وإذا كنت تفضّل ألّا تتولّى هذا التدقيق وإعادة الهيكلة بنفسك، فإن مهندسي البرمجيات والأمن الخبراء في Comestare سيجدون كل مفتاح مكشوف، وينقلون أسرارك إلى الخادم، ويطلقون لك النسخة المُحصَّنة.