This episode covers Gatsby site security: the security benefits of static sites, securing third-party scripts with SRI, content security policy and secure headers, and how to handle sensitive data and private content.

Static sites have a built-in security advantage: there's no server executing code per request, so many classic attacks like SQL injection and RCE aren't relevant. But security doesn't mean zero work — the risk shifts to the client side.
Episode 12 covers Gatsby site security: securing third-party scripts, content security policy and secure headers, and handling sensitive data and private content.
Even though Gatsby handles part of the risk automatically, the decisions still rest with you as a developer: every library you add, every header you send, and every piece of content you render needs to be audited one by one.
Because Gatsby produces static files, there's no backend to brute-force. The attacks that remain relevant are XSS (cross-site scripting), injected third-party scripts, and data leaks on the client. Recognizing the remaining attack surface is an honest first step.
User content rendered as HTML is the main XSS vector. Gatsby escapes output by default when rendering strings in JSX, so plain text is safe. Be careful when using dangerouslySetInnerHTML for content that comes from untrusted input — make sure it's sanitized with a library like dompurify:
import DOMPurify from "dompurify"
const aman = DOMPurify.sanitize(htmlDariPengguna)DOMPurify.sanitize removes scripts and dangerous attributes before the HTML is rendered. Never render raw HTML from an unknown source.
Scripts from a third-party CDN can be altered if that CDN is compromised. SRI ensures the browser only runs scripts whose hash matches:
<script
src="https://cdn.example.com/library.js"
integrity="sha384-A9b..."
crossorigin="anonymous"
></script>The integrity attribute holds a base64 hash of the script's content. If the content changes, the browser refuses to run it. The Gatsby Head API can render script tags with SRI on specific pages. You can compute the hash yourself via the command line and base64-encode it, or use a generator from a trusted source.
The fewer external scripts, the smaller the risk. Audit every analytics, widget, and font script: is it really needed? Lazy-load non-critical scripts so they only load when necessary. Keep a list of scripts running on every page and recheck it regularly — unused scripts often escape cleanup.
Also mind privacy: third-party scripts usually process visitor data and set cookies. Make sure the list of allowed scripts aligns with your site's privacy policy, and give visitors the option to decline non-essential tracking. A short script list also makes privacy audits easier.
A Content Security Policy tells the browser which sources are allowed to load scripts, styles, and media. With a strict CSP, script injection attacks are blocked even if they manage to sneak in. Example header:
[[headers]]
for = "/*"
[headers.values]
Content-Security-Policy = "default-src 'self'; script-src 'self' https://cdn.example.com"
X-Frame-Options = "DENY"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "strict-origin-when-cross-origin"The policy above only allows scripts from your own domain and the approved CDN. The other headers prevent clickjacking and content type sniffing. Start with a strict CSP, then add domains one at a time as production needs — that way you know exactly which script sources are circulating on your site.
To make things easier, there's gatsby-plugin-security-headers, which generates secure headers automatically on many platforms. Configure it in gatsby-config.js like any other plugin. Verify the result with curl:
curl -I https://situs-kalian.comThe curl -I command shows the response headers — check whether Content-Security-Policy, X-Frame-Options, and the others are present.
Remember the rule from episode 8: GATSBY_ variables get bundled into the browser. Never put an API key that must stay secret there. If a feature needs a secret — for instance, calling a paid API — do it through a serverless function called from the client.
Content intended only for certain users must not be rendered directly into static HTML, because it would be visible in the page's source code. Two approaches:
The details of authentication and gated content are covered thoroughly in episode 13. Meanwhile, make sure every endpoint that returns private data validates identity on the server side, not just relying on client-side protection.
Episode 12 completed security best practices: understanding the static site attack surface, securing third-party scripts with SRI, setting up CSP and secure headers, and safeguarding sensitive data and private content.
Key takeaways:
curl -I after deploying.In the next episode, episode 13, we'll discuss authentication and protected content — client-side auth patterns for Gatsby, integrating Netlify Identity and Firebase Auth, route protection, and safe token storage and rendering.