API-Schlüssel im Browser sichtbar? So prüfen Sie Ihren OpenAI-, Claude- oder Gemini-Key
Wenn eine Web-App OpenAI, Claude oder Gemini direkt aus dem Browser aufruft, liegt der API-Schlüssel offen und jeder mit geöffneten DevTools kann ihn kopieren. Über den Network-Tab lässt sich das in wenigen Minuten überprüfen.

Posted on Nov 2 • Originally published at apidog.com
إذا كان تطبيق الويب الخاص بك يستدعي OpenAI أو Claude أو Gemini مباشرةً من المتصفح، فإن مفتاح API الخاص بك مكشوف في المتصفح، وأي شخص يفتح DevTools يمكنه نسخه. يمكنك التأكد من ذلك في دقيقتين: افتح تبويب Network، أرسل طلب ذكاء اصطناعي واحد، وابحث عن ترويسة Authorization أو x-api-key أو x-goog-api-key المتجهة إلى مزوّد الخدمة. إذا رأيت مفتاحك هناك، فاستبدله اليوم وانقل الاستدعاء خلف مسار على الخادم.
فيما يلي: الفحص، وترتيب الإصلاح، وكيف يمكن لوكيل البرمجة الخاص بك اختبار المسار المُصلَّح.
مفتاح API المكشوف في المتصفح هو سرّ يُشحن داخل كود الواجهة الأمامية أو حركة الشبكة، حيث يمكن لكل زائر قراءته. وإذا أرسل المتصفح المفتاح، يمكن للمستخدم نسخه واستدعاء مزوّد الخدمة على حسابك.
يقول دليل مفتاح Gemini API من Google: «لا تُضمّن مفاتيح API مباشرةً في تطبيقات الويب أو الجوال» لأن «المفاتيح المُصرَّفة في كود جهة العميل يمكن للمستخدمين استخراجها»، وينصحك بأن «تشغّل خادمًا وسيطًا (proxy) في الخلفية لإجراء استدعاءات API الفعلية». ويقدّم دليل أمان مفتاح API من OpenAI القاعدة نفسها: مرّر الطلبات عبر خادمك الخلفي بدلًا من نشر المفتاح إلى جهة العميل.
يقول ملف README الخاص بـ openai-node إن دعم المتصفح معطّل افتراضيًا «لتجنّب كشف بيانات اعتماد API السرية الخاصة بك»، وعليك ضبط dangerouslyAllowBrowser: true لتفعيله. ويستخدم TypeScript SDK الخاص بـ Anthropic اسم الخيار نفسه، ولا يقبل API الخاص به استدعاءات المتصفح (CORS) إلا عندما يحمل الطلب الترويسة anthropic-dangerous-direct-browser-access: true ، كما وثّق Simon Willison عند إطلاقها.
هذا النمط شائع في التطبيقات المبنية بسرعة باستخدام أدوات بناء تطبيقات الذكاء الاصطناعي ووكلاء البرمجة: فأقصر مسار يعمل هو استدعاء fetch من مكوّن React مع المفتاح في متغيّر VITE_ أو NEXT_PUBLIC_. ثم يُعاد بيع المفاتيح المسروقة للاستدلال بالجملة، كما ورد في منشورنا حول مفاتيح AI API المسروقة وLLMjacking ، وتكون فاتورتك هي المكان الذي تلاحظ فيه ذلك.
نفّذ هذه الفحوصات على بيئة الإنتاج، لا على localhost.
grep -rnoE "sk-(proj-|ant-)?[A-Za-z0-9_-]{20,}|AIza[0-9A-Za-z_-]{35}" dist/ build/.next/static/ 2>/dev/null grep -rn "dangerouslyAllowBrowser" dist/ build/.next/static/ 2>/dev/null `
الإخراج الفارغ يعني النجاح. تقول Google إن مفاتيح AI Studio الجديدة المُنشأة منذ 28 مايو 2026 هي «مفاتيح مصادقة» (auth keys)، وقد يختلف تنسيقها عن AIza ، لذا ابحث أيضًا في الحزمة عن generativelanguage.googleapis.com. ولا تنجح إلا عندما يتحدث المتصفح إلى نطاقك الخاص (مثل /api/chat ) ولا يظهر أي اسم مضيف لمزوّد أو أي مفتاح في أي مكان.
الاستبدال أولًا يسدّ ثغرة اليوم؛ وتغيير البنية يسدّها نهائيًا.
انشر المفتاح الجديد على الخادم قبل أن تبطل المفتاح القديم، وإلا فسيتوقف عمل ميزة الذكاء الاصطناعي لديك. يغطي دليلنا حول أفضل ممارسات استبدال مفاتيح API الاستبدال دون أي توقف. وفي الخطوة 4، توصي إرشادات أمان المفاتيح من OpenAI بحدود إنفاق مع تطبيق صارم، لأن التنبيهات وحدها لا توقف الحركة؛ وميزانية الفوترة في Google Cloud تنبّهك لكنها لا توقف الاستخدام بحد ذاتها.
مسار الوسيط الخلفي هو نقطة نهاية خادم صغيرة تستقبل طلب المستخدم، وتضيف مفتاح API على الخادم، وتستدعي المزوّد، وتعيد الإجابة فقط. لا يرى المتصفح المفتاح أبدًا. إليك مسار Next.js بسيطًا لـ OpenAI؛ ويتبع Claude وGemini الشكل نفسه:
`ts // app/api/chat/route.ts (runs on the server only) import OpenAI from "openai"; import { getSession } from "@/lib/auth"; // your auth helper import { checkRateLimit } from "@/lib/limits"; // your per-user limiter
const client = new OpenAI({ [REDACTED CREDENTIAL] }); // no NEXT_PUBLIC_ prefix
export async function POST(req: Request) { const session = await getSession(req); if (!session) return new Response("Unauthorized", { status: 401 });
if (!(await checkRateLimit(session.userId, 20))) { // 20 requests per minute return new Response("Too many requests", { status: 429 }); }
const { message } = await req.json(); if (typeof message!== "string" || message.length > 4000) { return new Response("Bad request", { status: 400 }); }
const response = await client.responses.create({ model: process.env.OPENAI_MODEL!, // pin the model server-side input: message, });
return Response.json({ reply: response.output_text }); // return the answer, nothing else } `
أما بالنسبة لـ Claude وGemini، فاستخدم SDK الخاص بهما مع ANTHROPIC_API_KEY أو GEMINI_API_KEY. تساعد قيود الموقع وعنوان IP في Google، لكن أي شخص لديه curl يمكنه إرسال أي ترويسة Referer ، لذا تعامل معها كطبقة ثانية. والحالة الوحيدة المعقولة للاستدعاء من المتصفح هي أداة «أحضِر مفتاحك الخاص» حيث يلصق كل مستخدم مفتاحه الخاص.
نقل المفتاح نصف المهمة؛ والنصف الآخر هو إثبات أنه يبقى منقولًا بعد الميزة التالية التي يكتبها وكيلك. دع الوكيل الذي بنى المسار يختبره باستخدام Apidog CLI. أعِدّ ذلك مرة واحدة:
bash npm install -g apidog-cli@latest apidog login --with-token <YOUR_TOKEN> npx -y skills add https://apidog.com # pick your agent when prompted
ثم أعطِ Claude Code أو Codex أو Cursor أو أي وكيل تستخدمه موجهًا واحدًا:
`text Create Apidog test cases in project for POST /api/chat on our staging environment that assert:
يقرأ الوكيل المخطط، ويتحقق من صحة حمولته، ويكتب الحالات ويشغّلها:
bash apidog test-case category --project <id> apidog cli-schema get test-case-create apidog cli-schema validate test-case-create --file case.json apidog test-case create --project <id> --file case.json apidog run --test-case <caseId> --project <id> -e <envId> -r cli,json
التحقق الثاني هو الأهم: فهو يفشل في اللحظة التي يبدأ فيها كائن خطأ من المزوّد أو حقل تصحيح في إعادة مفتاحك إلى جهة العميل. ضع خطوة apidog run... -r junit نفسها في خط أنابيبك ليعيد كل نشر التحقق منها؛ ويوضح دليل Apidog CLI في CI/CD الإعداد، ويغطي Apidog CLI في Claude Code جانب الوكيل. تغطي الخطة المجانية من Apidog ما يصل إلى 4 مستخدمين، لذا يمكن لفريق صغير تشغيل هذا دون مقعد مدفوع.
أما بالنسبة لجانب المستودع من المشكلة نفسها، أي المفاتيح المُودَعة في Git بدلًا من شحنها إلى المتصفح، فراجع منشورنا حول فحص تسريب مفاتيح API باستخدام ماسح أسرار. وإذا كانت وكلاؤك يستدعون أدوات تتعامل مع بيانات العملاء، فمنشور اختبار وكلاء الذكاء الاصطناعي بحثًا عن تسريبات البيانات يغطي الطبقة التالية.
كيف أعرف ما إذا كان مفتاح OpenAI API الخاص بي مكشوفًا في المتصفح؟ شغّل ميزة ذكاء اصطناعي مع فتح تبويب Network في DevTools. وجود طلب إلى api.openai.com مع ترويسة Authorization: Bearer [REDACTED]-... يعني أنه مكشوف. وابحث أيضًا في السكربتات المُحمَّلة عن sk- و dangerouslyAllowBrowser.
هل من الآمن وضع مفتاح API في متغيّر بيئة NEXT_PUBLIC_ أو VITE_؟ لا. هذه البادئات موجودة لنسخ القيم إلى حزمة العميل. أي مفتاح مزوّد مخزَّن تحتها يُشحن إلى كل زائر. استخدم متغيّرًا غير مُبدوء ببادئة مخصّصًا للخادم واقرأه داخل مسار على الخادم.
هل تقييد مفتاح Gemini API بموقعي يجعله آمنًا في المتصفح؟ يساعد، لكن يمكن لسكربت خارج المتصفح إرسال أي ترويسة Referer. ويوصي دليل Google نفسه باستخدام وسيط خلفي لتطبيقات جهة العميل.
وجدت مفتاحي مكشوفًا. ماذا أفعل أولًا؟ أنشئ مفتاحًا جديدًا، وانشره على الخادم، ثم أبطِل القديم. بعد ذلك، انقل الاستدعاء خلف مسار مُوثَّق بحدود معدل لكل مستخدم، واضبط حدود الإنفاق لدى المزوّد.
هل يمكن لوكيل البرمجة الخاص بي إصلاح هذا واختباره نيابةً عني؟ نعم. اطلب منه نقل استدعاء المزوّد إلى مسار على الخادم، ثم استخدم Apidog CLI لإنشاء اختبارات وتشغيلها تتحقق من إرجاع 401 دون جلسة، وعدم وجود أنماط مفاتيح في الاستجابات، وإرجاع 429 بعد تجاوز حد المعدل.