Subresource Integrity (SRI) — Security

Apa itu Subresource Integrity? SRI (Subresource Integrity) adalah fitur keamanan browser yang memverifikasi bahwa file yang diambil dari CDN atau server…

SRI (Subresource Integrity) adalah atribut integrity di tag <script> atau <link> yang berisi sidik jari (hash) file yang kamu harapkan. Browser menghitung hash file yang benar-benar datang dari CDN, dan kalau beda, file itu gak dipakai. Bayangin kamu memesan obat, dan apotek memberimu kode yang dihitung dari isi obatnya. Saat paket datang, kamu hitung ulang kodenya dari isi paket. Satu butir saja ditukar, kodenya berubah total, dan obat itu gak kamu minum. Obatnya file JavaScript, kodenya hash di integrity, dan yang menghitung ulang adalah browser.

🧪 Tebakan cepat: file lib.js di CDN diubah satu karakter saja, "Rp" jadi "RP". Hash SHA-384-nya berubah sedikit, atau berubah total? Jawabannya ada di bagian "Hash: sidik jari sebuah file".

Kenapa file dari CDN perlu dicek

Waktu kamu menulis <script src="https://cdn.example.com/lib.js"></script>, file itu jalan di halamanmu dengan hak yang sama dengan kodemu sendiri: bisa membaca isi form, mengubah halaman, dan mengirim data ke mana pun. Kamu percaya CDN-nya gak pernah mengubah file itu. Kalau CDN dibobol, atau domain-nya pindah tangan, kode penyerang ikut jalan di semua situs yang memuatnya.

Ini pernah terjadi. Juni 2024, domain polyfill.io, yang script-nya dimuat lebih dari 100.000 situs, berganti pemilik dan mulai menyisipkan kode jahat ke file yang dikirimnya.

Hash: sidik jari sebuah file

Hash (kamu sudah kenal di pelajaran encryption-hashing-encoding) mengubah isi apa pun jadi sidik jari dengan panjang tetap. SHA-384 menghasilkan 48 byte, yang ditulis dalam base64 jadi 64 karakter. Isi yang sama selalu memberi hash yang sama, dan isi yang beda satu byte saja memberi hash yang beda total.

Ini file lib.js yang dipakai di Lab (80 byte):

function formatRupiah(angka) {
  return "Rp" + angka.toLocaleString("id-ID");
}
Isi file SHA-384 (base64)
asli, "Rp" 4vlMkCBntvautp0XME8R3vfkStzXNiOdjs7eLdGbNQUAyvrGf85spApwnczyyYQP
diubah, "RP" UYjeag08cU8lY+wb6XO31z0n+uxHaSMnWBkhqiz8S4Ys+/0sFZCSFKIbXv7FJkuZ

Cuma satu huruf p jadi P, tapi hash-nya berubah total, gak ada bagian yang mirip. Itu jawaban tebakannya. Penyerang gak bisa mengubah file dan tetap mempertahankan hash-nya.

Memasang integrity dan crossorigin

<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-4vlMkCBntvautp0XME8R3vfkStzXNiOdjs7eLdGbNQUAyvrGf85spApwnczyyYQP"
  crossorigin="anonymous"
></script>
Failed to find a valid digest in the 'integrity' attribute for resource 'https://cdn.example.com/lib.js' with computed SHA-384 integrity 'UYjeag08cU8lY+wb6XO31z0n+uxHaSMnWBkhqiz8S4Ys+/0sFZCSFKIbXv7FJkuZ'. The resource has been blocked.
Subresource Integrity: The resource 'https://cdn.example.com/lib.js' has an integrity attribute, but the resource requires the request to be CORS enabled to check the integrity, and it is not. The resource has been blocked because the integrity cannot be enforced.

Untuk CSS caranya sama: <link rel="stylesheet" href="..." integrity="sha384-..." crossorigin="anonymous">.

Membuat hash-nya

Di terminal, dengan file aslinya:

openssl dgst -sha384 -binary lib.js | openssl base64 -A
# 4vlMkCBntvautp0XME8R3vfkStzXNiOdjs7eLdGbNQUAyvrGf85spApwnczyyYQP

Atau di browser, dengan Web Crypto, cara yang sama yang dipakai Lab:

async function sriHash(text) {
  const bytes = new TextEncoder().encode(text);
  const digest = await crypto.subtle.digest("SHA-384", bytes);
  const base64 = btoa(String.fromCharCode(...new Uint8Array(digest)));
  return "sha384-" + base64;
}

Halaman cdnjs dan jsDelivr juga menampilkan tag lengkap dengan integrity yang siap disalin.

💡 Beberapa hash, dan batas SRI

Atribut integrity boleh berisi beberapa hash, dipisah spasi. Browser cuma memakai algoritma yang paling kuat di daftar itu, lalu menerima file kalau cocok dengan salah satu hash algoritma tersebut. Jadi integrity="sha384-AAA sha384-BBB" menerima dua versi file.

Batas yang perlu kamu tahu:

⚠️ Jebakan yang sering ketemu

TL;DR: SRI (Subresource Integrity) menaruh hash file di atribut integrity, dan browser menolak file dari CDN yang hash-nya gak cocok. Formatnya sha384- diikuti hash base64, misalnya sha384-4vlMkCBntvautp0XME8R3vfkStzXNiOdjs7eLdGbNQUAyvrGf85spApwnczyyYQP untuk lib.js di Lab. Ubah satu karakter saja dan hash-nya berubah total. Untuk file dari origin lain wajib tambahkan crossorigin="anonymous", kalau gak, file-nya diblokir karena hash-nya gak bisa dicek. Buat hash dengan openssl dgst -sha384 -binary lib.js | openssl base64 -A atau crypto.subtle.digest("SHA-384", ...). SRI cuma untuk <script> dan stylesheet yang isinya tetap, jadi pakai URL dengan versi tetap.

Yang akan kamu pelajari