API Key Bocor di Browser? Cek Kunci OpenAI, Claude, atau Gemini dalam 2 Menit

Jika aplikasi Anda memanggil OpenAI, Claude, atau Gemini langsung dari browser, siapa pun dapat menyalin kunci dari DevTools. Pemeriksaan 2 menit, urutan perbaikan, dan bagaimana agen coding Anda dapat menguji rute proxy.

Ashley Innocent

Ashley Innocent

2 November 2026

API Key Bocor di Browser? Cek Kunci OpenAI, Claude, atau Gemini dalam 2 Menit

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

Jika aplikasi web Anda memanggil OpenAI, Claude, atau Gemini langsung dari browser, kunci API Anda terekspos di browser, dan siapa pun yang membuka DevTools dapat menyalinnya. Anda dapat membuktikannya dalam 2 menit: buka tab Network, kirim satu permintaan AI, lalu cari header Authorization, x-api-key, atau x-goog-api-key yang menuju ke penyedia. Jika Anda melihat kunci Anda di sana, rotasi kunci itu hari ini juga dan pindahkan panggilan ke balik rute server.

Di bawah ini: cara pengecekannya, urutan perbaikannya, dan bagaimana coding agent Anda dapat menguji rute yang sudah diperbaiki.

Mengapa kunci API yang terekspos di browser menjadi masalah

Kunci API yang terekspos di browser adalah rahasia yang ikut terkirim di dalam kode frontend atau lalu lintas jaringan Anda, tempat setiap pengunjung dapat membacanya. Jika browser yang mengirim kunci tersebut, pengguna dapat menyalinnya dan memanggil penyedia dengan tagihan Anda.

Panduan kunci API Gemini dari Google menyatakan “Jangan menuliskan kunci API secara hardcode langsung di aplikasi web atau mobile” karena “Kunci yang dikompilasi ke dalam kode sisi klien dapat diekstrak oleh pengguna,” dan panduan itu menyarankan Anda untuk “menjalankan server proxy backend untuk melakukan panggilan API yang sebenarnya.” Panduan keamanan kunci API dari OpenAI memberikan aturan yang sama: arahkan permintaan melalui backend Anda sendiri alih-alih men-deploy kunci ke klien.

README openai-node menyatakan dukungan browser dinonaktifkan secara default “untuk menghindari mengekspos kredensial API rahasia Anda,” dan Anda harus menyetel dangerouslyAllowBrowser: true untuk mengaktifkannya. SDK TypeScript dari Anthropic menggunakan nama opsi yang sama, dan API-nya hanya menerima panggilan browser (CORS) ketika permintaan membawa header anthropic-dangerous-direct-browser-access: true, seperti yang didokumentasikan Simon Willison saat fitur itu dirilis.

Pola ini umum ditemukan pada aplikasi yang dibangun dengan cepat menggunakan AI app builder dan coding agent: jalur terpendek yang berhasil adalah fetch dari komponen React dengan kunci disimpan di variabel VITE_ atau NEXT_PUBLIC_. Kunci yang dicuri kemudian dijual kembali untuk inferensi massal, seperti dibahas dalam artikel kami tentang kunci API AI yang dicuri dan LLMjacking, dan tagihan Andalah tempat Anda menyadarinya.

Cara memeriksa apakah kunci API Anda terekspos (2 menit)

Three-step infographic of the 2-minute key exposure check: 1 Network tab with a POST request highlighted, 2 search the JavaScript bundle for sk- and AIza, 3 check env vars prefixed NEXT_PUBLIC_ or VITE_

Jalankan pemeriksaan ini pada produksi, bukan localhost.

  1. Amati tab Network (45 detik). Buka situs Anda, tekan F12 (Cmd+Option+I di Mac), pilih tab Network dan picu satu fitur AI, misalnya mengirim pesan chat. Filter berdasarkan openai, anthropic, atau googleapis. Jika ada permintaan yang langsung menuju api.openai.com, api.anthropic.com, atau generativelanguage.googleapis.com, klik permintaan itu dan buka Headers. Kunci yang ada di Authorization: Bearer, x-api-key, x-goog-api-key, atau parameter kueri ?key= berarti kunci tersebut terekspos.
  2. Cari di bundle (45 detik). Di DevTools, tekan Cmd+Option+F (Ctrl+Shift+F di Windows) untuk mencari di semua skrip yang dimuat. Cari sk-, sk-ant-, AIza, dan dangerouslyAllowBrowser. Temuan apa pun di berkas .js yang dikirim ke browser adalah kebocoran, bahkan jika belum ada permintaan yang dikirim.
  3. Periksa prefiks variabel env Anda (30 detik). Buka berkas .env dan dasbor hosting Anda. Build tool menyalin sebagian variabel ke dalam bundle klien secara sengaja: VITE_* di Vite (lihat dokumentasi env Vite), NEXT_PUBLIC_* di Next.js, REACT_APP_* di Create React App, dan EXPO_PUBLIC_* di Expo. Kunci penyedia yang berada di balik salah satu prefiks tersebut bersifat publik, apa pun namanya.

Untuk pemindaian hasil build Anda lewat terminal:

# from your project root after a production build
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

Output kosong berarti lulus. Google menyatakan kunci AI Studio baru yang dibuat sejak 28 Mei 2026 adalah “auth key,” yang formatnya mungkin berbeda dari AIza, jadi cari juga generativelanguage.googleapis.com di bundle. Anda baru lulus jika browser hanya berkomunikasi dengan domain Anda sendiri (misalnya /api/chat) dan tidak ada hostname penyedia atau kunci yang muncul di mana pun.

Apa yang harus dilakukan saat kunci Anda terekspos: urutan perbaikan

Merotasi kunci lebih dulu menutup celah hari ini; perubahan arsitektur menutupnya untuk selamanya.

Langkah Yang Anda lakukan Mengapa urutan ini Waktu
1. Rotasi kunci Buat kunci baru di konsol penyedia, lalu cabut kunci yang bocor Kunci lama mungkin sudah disalin; mencabutnya adalah satu-satunya hal yang menghentikan penggunaannya 5 menit
2. Pindahkan panggilan ke sisi server Letakkan panggilan penyedia di rute server atau edge function yang menyimpan kunci Mencegah kunci baru bocor dengan cara yang sama 30 sampai 60 menit
3. Tambahkan autentikasi dan pembatasan laju per pengguna Wajibkan sesi pada rute tersebut dan batasi jumlah permintaan per pengguna Tanpa ini, proxy Anda menjadi endpoint AI gratis bagi siapa pun 30 menit
4. Tetapkan batas pengeluaran penyedia Tetapkan anggaran atau batas pengeluaran di pengaturan penagihan setiap penyedia Membatasi tagihan terburuk jika ada hal lain yang bocor 10 menit
5. Pindai di CI Gagalkan build jika pola kunci muncul di bundle output Mencegah fitur berikutnya yang ditulis agent membatalkan perbaikan ini 15 menit

Deploy kunci baru di sisi server sebelum Anda mencabut kunci lama, atau fitur AI Anda akan mati. Panduan kami tentang praktik terbaik rotasi kunci API membahas rotasi tanpa downtime. Pada langkah 4, panduan keamanan kunci OpenAI merekomendasikan batas pengeluaran dengan penegakan yang keras, karena peringatan saja tidak menghentikan lalu lintas; anggaran penagihan Google Cloud hanya memberi peringatan tetapi tidak menghentikan penggunaan dengan sendirinya.

Cara memindahkan panggilan OpenAI, Claude, dan Gemini ke balik rute server

Diagram comparing an unsafe setup, where the browser holds the API key and calls the AI provider directly while DevTools copies the key, with a safe setup where the browser calls your server route, which holds the key and applies auth, rate limits and a spend cap before calling the provider

Rute proxy backend adalah endpoint server kecil yang menerima prompt pengguna, menambahkan kunci API di server, memanggil penyedia, dan hanya mengembalikan jawabannya. Browser tidak pernah melihat kuncinya. Berikut rute Next.js minimal untuk OpenAI; Claude dan Gemini mengikuti pola yang sama:

// 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({ apiKey: process.env.OPENAI_API_KEY }); // 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
}

Apa yang membuatnya aman, bukan sekadar tersembunyi:

Untuk Claude dan Gemini, gunakan SDK mereka dengan ANTHROPIC_API_KEY atau GEMINI_API_KEY. Pembatasan website dan IP dari Google membantu, tetapi siapa pun dengan curl dapat mengirim header Referer apa pun, jadi anggap itu sebagai lapisan kedua. Satu kasus yang wajar untuk panggilan dari browser adalah alat bring-your-own-key di mana setiap pengguna menempelkan kunci mereka sendiri.

Biarkan coding agent Anda menguji rute proxy dengan Apidog CLI

Memindahkan kunci baru separuh pekerjaan; separuh lainnya adalah membuktikan kunci itu tetap di tempatnya setelah fitur berikutnya ditulis oleh agent Anda. Biarkan agent yang membangun rute tersebut mengujinya dengan Apidog CLI. Siapkan sekali saja:

npm install -g apidog-cli@latest
apidog login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com   # pick your agent when prompted

Lalu berikan satu prompt kepada Claude Code, Codex, Cursor, atau agent apa pun yang Anda gunakan:

Create Apidog test cases in project <id> for POST /api/chat on our staging
environment that assert:
1. a request without a session cookie returns 401,
2. a valid request returns 200 and the body does not contain "sk-", "sk-ant-",
   "AIza" or "api_key",
3. the 21st request inside 60 seconds from the same user returns 429.
Run them and summarize any failures.

Agent tersebut membaca skema, memvalidasi payload-nya, menulis test case, dan menjalankannya:

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

Asersi kedua adalah yang paling penting: ia akan gagal begitu objek error penyedia atau field debug mulai mengembalikan kunci Anda ke klien. Letakkan langkah apidog run ... -r junit yang sama di pipeline Anda agar setiap deploy memeriksanya ulang; panduan CI/CD Apidog CLI kami menunjukkan cara penyiapannya, dan Apidog CLI di Claude Code membahas sisi agent-nya. Paket Free Apidog mencakup hingga 4 pengguna, jadi tim kecil dapat menjalankan ini tanpa kursi berbayar.

Untuk sisi repositori dari masalah yang sama, yaitu kunci yang di-commit ke Git alih-alih dikirim ke browser, lihat artikel kami tentang pemeriksaan kebocoran kunci API dengan secret scanner. Jika agent Anda memanggil tool yang menangani data pelanggan, pengujian agent AI untuk kebocoran data membahas lapisan berikutnya.

Kesalahan umum yang membuat kunci tetap terekspos

button

FAQ

Bagaimana saya tahu apakah kunci API OpenAI saya terekspos di browser? Picu fitur AI dengan tab Network DevTools terbuka. Permintaan ke api.openai.com dengan header Authorization: Bearer sk-... berarti kunci tersebut terekspos. Cari juga sk- dan dangerouslyAllowBrowser di skrip yang dimuat.

Apakah aman menaruh kunci API di variabel lingkungan NEXT_PUBLIC_ atau VITE_? Tidak. Prefiks tersebut ada untuk menyalin nilai ke dalam bundle klien. Kunci penyedia apa pun yang disimpan di bawah prefiks itu akan terkirim ke setiap pengunjung. Gunakan variabel khusus server tanpa prefiks dan bacalah di dalam rute server.

Apakah membatasi kunci API Gemini hanya untuk situs web saya membuatnya aman di browser? Itu membantu, tetapi skrip di luar browser dapat mengirim header Referer apa pun. Panduan Google sendiri merekomendasikan proxy backend untuk aplikasi klien.

Saya menemukan kunci saya terekspos. Apa yang harus saya lakukan lebih dulu? Buat kunci baru, deploy di sisi server, lalu cabut kunci lama. Selanjutnya, pindahkan panggilan ke balik rute terautentikasi dengan pembatasan laju per pengguna, dan tetapkan batas pengeluaran penyedia.

Bisakah coding agent saya memperbaiki dan mengujinya untuk saya? Bisa. Minta agent memindahkan panggilan penyedia ke rute server, lalu gunakan Apidog CLI untuk membuat dan menjalankan pengujian yang memastikan respons 401 tanpa sesi, tidak ada pola kunci di respons, dan respons 429 setelah melewati batas laju Anda.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.