CSP FOR STATIC SITES
The directives that actually matter for static sites in 2026, plus the FAL + Supabase + Pagefind playbook from gautamkhorana.com.
What CSP is for
Content Security Policy एक HTTP header है जो ब्राउज़र को बताता है कि आपके पेज के लिए किन origins से resources load करने की अनुमति है। सही तरीके से किया जाए तो यह ज़्यादातर XSS, clickjacking, और supply-chain attacks को रोकता है। गलत तरीके से किया जाए तो यह चुप-चाप ऐसे तरीकों से features को तोड़ता है जिन्हें diagnose करने में दिन लग जाते हैं।
Static sites अपनी CSP को under-document करते हैं क्योंकि perceived risk कम होता है। हकीकत यह है कि एक missing CSP directive वाली static site video playback, image loading, search functionality, या font rendering को तोड़ सकती है, और ब्राउज़र console message ही एकमात्र signal है जो आपको मिलता है।
Per-resource-type mapping
वह directive जो हर resource type को control करता है:
img-src के लिए img tags। video, audio, source elements के लिए media-src। iframe के लिए frame-src। fetch और WebSocket के लिए connect-src। script tags के लिए script-src। style tags और link rel=stylesheet के लिए style-src। @font-face के लिए font-src।
Critical: default-src "self" तीसरे पक्ष के होस्ट से video को कवर नहीं करता। Supabase Storage से video को यदि आप media-src भूल जाएँ तो सिर्फ poster के साथ चुप-चाप खेलने में विफल होगा। Browser console उस directive को दिखाता है जिसने इसे रोका; जब video mysteriously खेलना न चले तो पहले वह देखें।
May 2026 की घटना
gautamkhorana.com पर May 2026 में, एक Kling MP4 जो Supabase Storage पर होस्ट था, HTML को सही तरह render तो कर गया लेकिन कभी खेला नहीं। Poster image दिखा; video शुरू नहीं होगा। बीस मिनट की debugging के बाद जवाब यह था कि CSP के पास कोई media-src directive नहीं था और browser video element को चुप-चाप block कर रहा था।
Fix netlify.toml में एक पंक्ति जोड़ना था: media-src "self" https://*.supabase.co। Poster-but-no-playback symptom असली pattern है: इसका मतलब है कि CSP image को तो allow करता है लेकिन video को नहीं।
Static-search libraries को wasm और worker permissions चाहिए
Pagefind, Stork, Tinysearch, और अन्य static-site search libraries WebAssembly plus Web Workers use करते हैं। CSP में script-src "wasm-unsafe-eval" AND worker-src "self" blob: होना चाहिए या search forever "Searching..." पर hang हो जाएगा और कोई console error नहीं होगा।
gautamkhorana.com पर May 2026 की दूसरी घटना: search drawer "Searching..." पर stuck था क्योंकि pagefind.init() चुप-चाप fail हुआ था जब wasm को block किया गया था। Fix script-src में "wasm-unsafe-eval" जोड़ना और worker-src में "self" blob: जोड़ना था।
FAL + Supabase + Pagefind sites के लिए minimum-viable CSP
Required:
img-src self https://*.supabase.co https://*.fal.media, hero images और FAL-generated assets के लिए। media-src self https://*.supabase.co, video के लिए। connect-src self https://*.supabase.co, Supabase API calls के लिए। script-src self "wasm-unsafe-eval", Pagefind के लिए। worker-src self blob:, Pagefind workers के लिए। style-src self "unsafe-inline", Astro scoped styles के लिए। font-src self, self-hosted fonts के लिए।
जब भी आप कोई नया asset host जोड़ते हैं (Cloudinary, Bunny, R2, कुछ भी), netlify.toml या vercel.json को audit करें और उस host को हर directive में जोड़ें जो उस resource type के लिए जरूरी हो सकता है। गलत करने की कीमत एक silent break है जो production में सामने आता है।
CSP changes को test करना
CSP-Report-Only mode आपको production में policy changes को बिना कुछ तोड़े test करने देता है। browser logs को-be violations को blocking के बजाय एक reporting endpoint पर भेजता है। किसी भी नए directive को एक हफ्ते के लिए report-only mode में run करें, violations को review करें, फिर enforcing में promote करें।
ज्यादातर CSP failures production में silent होती हैं। एक reporting endpoint ही एकमात्र तरीका है जिससे पता चल सकता है कि आपने असल में क्या तोड़ा है। किसी भी non-trivial CSP change को ship करने से पहले एक setup कर लें।