Security Blog

Lihat Sumber, Salin Kunci, Kuasai Segalanya

#54

October 2, 2026 · By Marketing team

← All posts

Seorang peneliti membuka sumber halaman ClickUp, menemukan kunci API yang di-hardcode di JavaScript, lalu menggunakannya untuk mengambil 959 alamat email dan 3.165 fitur flag internal dalam satu permintaan. Kunci tersebut tidak memiliki scope, tidak memiliki batas laju, dan tidak memiliki masa berlaku.

Seorang peneliti keamanan membuka clickup.com. Membuka sumber halaman. Menemukan kunci API yang di-hardcode di JavaScript. Menyalinnya. Mengirim satu permintaan GET.

Mendapat kembali 959 alamat email dan 3.165 fitur flag internal. Para karyawan dari Home Depot. Fortinet. Autodesk. Tenable. Rakuten. Mayo Clinic.

Satu string. Satu permintaan. Segalanya.

Bagaimana ini bisa terjadi

Seseorang membutuhkan frontend untuk memanggil sebuah API. API tersebut membutuhkan autentikasi. Jadi mereka meletakkan kunci itu di JavaScript. Rilis, lanjut, sprint berikutnya.

Ini bukan serangan canggih. Tidak ada eksploit, tidak ada zero-day, tidak ada social engineering. Ini hanya view-source: dan curl. Sebuah browser dan sebuah terminal. Semacam hal yang dilakukan seorang magang penasaran di hari pertamanya.

Kunci itu tidak punya scope — kunci itu bisa mengakses semua yang diekspos oleh API. Tidak ada batas laju — satu permintaan mengembalikan semuanya. Tidak ada masa berlaku — kunci itu berfungsi sampai ada yang menyadarinya. Tidak ada faktor kedua — kepemilikan string itu adalah satu-satunya gerbang.

Sudut pandang finansial

Orang membicarakan tentang paparan data. Mari kita bicarakan berapa nilai data ini.

959 alamat email korporat dari perusahaan Fortune 500. Itu adalah daftar target spear-phishing yang dibayar oleh para aktor ancaman. Nama, peran, dan fakta bahwa perusahaan-perusahaan ini menggunakan ClickUp — itulah konteks social engineering yang membuat phishing berhasil.

3.165 fitur flag internal. Itu adalah sebuah roadmap. Ini memberi tahu pesaing apa yang sedang dibangun ClickUp, apa yang sedang mereka uji, apa yang ada di balik sebuah gerbang. Ini memberi tahu penyerang fitur mana yang setengah jadi dan kemungkinan rentan.

Ini bukan insiden privasi. Ini adalah kebocoran business intelligence.

Mengapa ini terus terjadi

Ini adalah insiden kredensial-dalam-sumber keempat yang kami tulis bulan ini. CLI Bitwarden mengalami kredensial yang diambil karena berupa file plaintext. Variabel lingkungan Vercel dapat didekripsi karena flag "sensitive" tidak diaktifkan secara default. Seorang pengembang kehilangan 634 kata sandi Chrome karena kunci dekripsi berada di disk yang sama.

Pola selalu sama: sebuah kredensial ada sebagai string — di sebuah file, di sebuah variabel, di sumber halaman — dan sesuatu membacanya. Sesuatu itu berubah. Pola itu tidak.

Kunci API dalam JavaScript adalah versi paling buruk karena tidak diperlukan serangan apa pun. Kunci itu dipublikasikan. Kunci itu disajikan kepada setiap pengunjung. Browser mengunduhnya, merender, dan menampilkannya kepada siapa pun yang klik kanan.

Seharusnya apa yang berbeda

Panggilan API seharusnya tidak pernah diautentikasi dengan kunci statis dari sisi klien. Pilihannya:

  • Backend proxy. Frontend memanggil backend Anda sendiri, yang menyimpan kunci di sisi server dan meneruskan panggilan API. Kunci tidak pernah sampai ke browser.
  • Token berbasis sesi. Frontend mendapatkan token berumur pendek dengan scope sempit setelah autentikasi. Token itu kedaluwarsa. Token itu hanya bisa melakukan apa yang diizinkan untuk pengguna yang terautentikasi. Token itu bukan kunci utama.
  • Tanpa kunci sama sekali. Jika data bersifat publik, sajikan tanpa autentikasi. Jika tidak publik, jangan sajikan kepada JavaScript yang tidak terautentikasi.

Meng-hardcode kunci API dalam kode sisi klien sama dengan meletakkan kunci rumah Anda di bawah keset dan mempublikasikan alamat Anda.

Masalah siklus hidup kredensial

Kunci ClickUp ini kemungkinan dibuat sekali, ditempel ke sebuah file JavaScript, di-commit ke sebuah repo, dideploy ke produksi, dan tidak pernah dipikirkan lagi. Tidak ada yang merotasinya. Tidak ada yang memberinya scope. Tidak ada yang menetapkan masa berlaku. Tidak ada yang memantau apa yang diaksesnya.

Itulah siklus hidup sebagian besar kunci API di sebagian besar organisasi. Dibuat terburu-buru, ditempel di tempat yang dibutuhkan, lalu dilupakan. Kunci-kunci itu menumpuk di seluruh basis kode, file konfigurasi, pipeline CI/CD, dan ternyata juga di sumber halaman — masing-masing sebuah pintu yang tidak pernah terkunci.

Pertanyaannya bukan apakah organisasi Anda memiliki kunci seperti ini. Pertanyaannya adalah berapa banyak yang Anda miliki, dan apakah Anda akan tahu jika seseorang menyalin salah satunya hari ini.