Login atau daftar akun gratis untuk membaca cheat sheet ini.
Cheat sheet ini berisi kumpulan HTTP security headers yang penting buat melindungi aplikasi web kamu dari serangan umum seperti XSS, clickjacking, MIME sniffing, dan lainnya. Setiap header punya contoh konfigurasi untuk Express.js dan Next.js middleware.
CSP adalah header yang membatasi sumber daya apa saja (script, style, image, font) yang boleh dimuat oleh browser. Header ini paling efektif untuk mencegah Cross-Site Scripting (XSS) dan data injection attacks.
| Directive | Fungsi |
|---|---|
default-src | Default policy untuk semua resource type |
script-src | Sumber JavaScript yang diizinkan |
style-src | Sumber CSS yang diizinkan |
img-src | Sumber gambar yang diizinkan |
font-src| Sumber font yang diizinkan |
connect-src | Endpoint fetch, XHR, WebSocket |
frame-src | URL iframe yang diizinkan |
object-src | Plugin seperti Flash, Java |
base-uri | URL base yang diizinkan |
form-action | Endpoint form submission |
Content-Security-Policy: default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
object-src 'none';Untuk inline script yang aman, gunakan nonce (number used once) yang di generate setiap request.
Content-Security-Policy: script-src 'self' 'nonce-abc123random456';<script nonce="abc123random456">
console.log("Script ini diizinkan CSP");
</script>import helmet from "helmet";
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'",
// middleware.js
export function middleware(request) {
const nonce = crypto.randomUUID().replace(/-/g,
Kalau kamu masih testing CSP tanpa blocking, pakai Content-Security-Policy-Report-Only untuk mengirim laporan ke endpoint tanpa memblokir resource.
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report;HSTS memaksa browser untuk selalu menggunakan HTTPS saat mengakses domain kamu. Ini mencegah serangan SSL stripping dan man-in-the-middle.
| Directive | Fungsi |
|---|---|
max-age | Lama (detik) browser mengingat untuk pakai HTTPS |
includeSubDomains | Berlaku untuk semua subdomain |
preload | Memungkinkan dimasukkan ke HSTS preload list browser |
Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadapp.use(
helmet.hsts({
maxAge: 31536000, // 1 tahun dalam detik
includeSubDomains: true,
preload: true,
})
);// next.config.js
const securityHeaders = [
{
key: "Strict-Transport-Security",
value: "max-age=31536000; includeSubDomains; preload",
},
];
module.exports = {
async headers() {
return
Header ini mencegah clickjacking dengan mengontrol apakah halaman kamu bisa di embed di iframe.
| Nilai | Arti |
|---|---|
DENY | Halaman tidak bisa di-frame sama sekali |
SAMEORIGIN | Hanya boleh di-frame oleh origin yang sama |
X-Frame-Options: DENY// Helmet sudah set frameguard ke SAMEORIGIN secara default
app.use(
helmet.frameguard({
action: "deny", // atau "sameorigin"
})
);Kalau kamu sudah set frame-ancestors di CSP, browser modern akan mengabaikan X-Frame-Options. Tapi tetap disarankan untuk set keduanya demi dukungan browser lama.
Header ini mencegah browser melakukan MIME sniffing, yaitu menebak tipe konten file yang berbeda dari yang di deklarasikan server.
X-Content-Type-Options: nosniffapp.use(helmet.noSniff()); // Sudah aktif secara default di helmetconst securityHeaders = [
{
key: "X-Content-Type-Options",
value: "nosniff",
},
];Header ini mengontrol informasi referrer (URL asal) yang dikirim browser saat user mengklik link atau memuat resource dari domain lain.
| Nilai | Perilaku |
|---|---|
no-referrer | Tidak mengirim referrer sama sekali |
no-referrer-when-downgrade | Tidak kirim saat HTTPS ke HTTP (default browser) |
same-origin | Hanya kirim referrer ke origin yang sama |
origin | Hanya kirim origin, bukan full URL |
strict-origin | Hanya kirim origin, tidak saat downgrade |
origin-when-cross-origin | Full URL untuk same-origin, origin saja untuk cross-origin |
strict-origin-when-cross-origin | Full URL same-origin, origin saja cross-origin (default browser modern) |
unsafe-url | Selalu kirim full URL (tidak disarankan) |
Referrer-Policy: strict-origin-when-cross-originapp.use(
helmet.referrerPolicy({
policy: ["strict-origin-when-cross-origin"],
})
);Header ini (dulunya Feature-Policy) mengontrol fitur browser apa saja (kamera, mikrofon, geolocation, payment) yang boleh dipakai oleh halaman kamu dan iframe yang di embed.
Permissions-Policy: camera=(), microphone=(), geolocation=(self "https://trusted.com"), payment=*| Directive | Fungsi |
|---|---|
camera | Akses kamera |
microphone | Akses mikrofon |
geolocation | Akses lokasi GPS |
payment | Payment Request API |
fullscreen | Fullscreen API |
usb | WebUSB API |
clipboard-read | Baca clipboard |
clipboard-write | Tulis clipboard |
app.use(
helmet.permissionsPolicy({
directives: {
camera: [],
microphone: [],
geolocation: ["self"],
payment: ["self"],
fullscreen: ["self"],
},
})
);| Nilai | Arti |
|---|---|
() | Disabled untuk semua |
(self) | Hanya untuk origin yang sama |
("https://example.com") | Hanya untuk origin spesifik |
* | Enabled untuk semua |
Cross-Origin Resource Sharing (CORS) adalah mekanisme browser yang mengizinkan server menentukan origin mana saja yang boleh mengakses resource-nya. CORS bukan header tunggal tapi kombinasi beberapa header.
| Header | Fungsi |
|---|---|
Access-Control-Allow-Origin | Origin mana yang diizinkan |
Access-Control-Allow-Methods | HTTP method yang diizinkan |
Access-Control-Allow-Headers | Custom header yang diizinkan |
Access-Control-Allow-Credentials | Bolehkah kirim cookie |
Access-Control-Max-Age | Cache preflight request (detik) |
Access-Control-Expose-Headers | Header response yang boleh dibaca JS |
Simple request langsung dikirim tanpa preflight jika memenuhi syarat: method GET/HEAD/POST, header hanya yang CORS-safe, dan Content-Type hanya text/plain, multipart/form-data, atau application/x-www-form-urlencoded.
Preflight request dikirim sebagai OPTIONS request sebelum request sebenarnya untuk method seperti PUT/DELETE atau custom header.
import cors from "cors";
// Konfigurasi sederhana
app.use(
cors({
origin: "https://example.com", // atau array ["https://a.com", "https://b.com"]
methods: ["GET", "POST"
app.use((req, res, next) => {
const allowedOrigins = ["https://app.com", "https://admin.app.com"];
const origin =
Kalau kamu set Access-Control-Allow-Credentials: true, maka Access-Control-Allow-Origin tidak boleh *. Harus spesifik origin.
Tiga header ini dipakai untuk mencapai cross-origin isolation, yang diperlukan untuk fitur seperti SharedArrayBuffer dan high-resolution timers.
Mencegah halaman memuat cross-origin resource yang tidak mengizinkannya.
Cross-Origin-Embedder-Policy: require-corpNilai:
unsafe-none (default): Halaman bisa memuat cross-origin resource tanpa CORP headerrequire-corp: Resource harus set CORP header atau di opt-in lewat crossorigin attributeMengisolasi browsing context group untuk mencegah serangan seperti Spectre yang mengeksploitasi window references.
Cross-Origin-Opener-Policy: same-originNilai:
unsafe-none (default): Tidak ada isolasisame-origin-allow-popups: Isolasi tapi boleh window popupsame-origin: Isolasi penuh, window references terputusMengunci resource (image, script, font) hanya untuk origin tertentu.
Cross-Origin-Resource-Policy: same-originNilai:
same-origin: Hanya origin yang sama bisa memuatsame-site: Hanya site yang samacross-origin: Semua origin boleh (tapi tetap butuh CORS)Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-originapp.use((req, res, next) => {
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader(
const isCrossOriginIsolated = self.crossOriginIsolated;
console.log("Cross-origin isolated:", isCrossOriginIsolated);Daftar lengkap header yang harus di set untuk keamanan optimal:
| Header | Prioritas | Target |
|---|---|---|
| Content-Security-Policy | Tinggi | Semua halaman HTML |
| Strict-Transport-Security | Tinggi | Semua HTTPS response |
| X-Content-Type-Options | Tinggi | Semua response |
| X-Frame-Options | Sedang | Halaman sensitif |
| Referrer-Policy | Sedang | Semua response |
| Permissions-Policy | Sedang | Semua halaman HTML |
| Access-Control-Allow-Origin | Tinggi | API endpoint cross-origin |
| COEP | Opsional | Aplikasi yang butuh SharedArrayBuffer |
| COOP | Opsional | Aplikasi yang butuh SharedArrayBuffer |
Helmet secara default mengaktifkan sebagian besar security headers penting. Berikut konfigurasi yang lengkap:
import helmet from "helset";
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
Gunakan tool berikut untuk audit security headers:
https://example.com).app.example.com dan api.example.com).