Up to date
Published
3 min read

Trevor I. Lasn

Staff Software Engineer, Engineering Manager

How To Implement Content Security Policy (CSP) Headers For Astro

Content Security Policy (CSP) acts like a shield against XSS attacks. These attacks are sneaky - they trick your browser into running malicious code by hiding it in content that seems trustworthy. CSP's job is to spot these tricks and shut them down, while also alerting you to any attempts it detects.

Content Security Policy is like a bouncer for your website. It tells the browser what content is allowed to load and from where. This helps prevent a whole bunch of nasty attacks, like Cross-Site Scripting (XSS) and data injection.

Content Security Policy (CSP) should be implemented as a response header, not a request header. Here’s why:

  1. CSP is a security mechanism enforced by the browser on the client-side.
  2. The server sends the CSP directives to the browser as part of its response.
  3. The browser then enforces these policies when loading and executing content.

So, in the context of Astro.js and web servers in general, CSP headers should be set on the server’s responses to the client. This means that when configuring CSP, we’re always dealing with response headers.

Let’s start with a basic CSP setup for an Astro site. We’ll use the astro.config.mjs file to add our headers.

import { defineConfig } from 'astro/config';
export default defineConfig({
server: {
headers: {
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
}
}
});
  1. default-src 'self': Only allows resources to be loaded from the same origin.
  2. script-src 'self' 'unsafe-inline': Allows scripts from the same origin and inline scripts (which Astro uses).
  3. style-src 'self' 'unsafe-inline': Allows styles from the same origin and inline styles.

The Astro CSP Gotcha

Astro has a unique architecture that can trip up CSP. It uses a technique called “partial hydration” where some components are static and others are interactive. This means your CSP needs to be flexible enough to allow for this hybrid approach.

Here’s a more comprehensive CSP for a typical Astro site.

export default defineConfig({
server: {
headers: {
"Content-Security-Policy": `
default-src 'self';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
block-all-mixed-content;
upgrade-insecure-requests;
`
}
}
});

This policy is more permissive but still secure. It allows for Astro’s hydration needs 'unsafe-eval' and common use cases like loading images from HTTPS sources.

Vercel Approach

With Vercel, you can use a vercel.json file in your project root:

{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
}
]
}
]
}

This applies the CSP header to all routes on your Vercel-deployed Astro site. All you have to do with git push to deploy your changes.

Cloudflare Approach

Cloudflare uses Page Rules to add headers. Here’s how you might set it up:

  1. Go to your Cloudflare dashboard
  2. Navigate to Rules > Page Rules
  3. Click on the ‘Modify Response Headers’ tab
  4. Click ‘Create rule’
  5. Click ‘Add Static Header to Response’
  6. Add a “CSP” Header:
    • Header Name: Content-Security-Policy
    • Value: Your CSP string

Cloudflare Page Rule

The advantage of Cloudflare’s approach is that you can easily update your CSP without redeploying your site.

Read Also


Found this article helpful? You might enjoy my free newsletter. I share dev tips and insights to help you grow your coding skills and advance your tech career.

Interested in supporting this blog in exchange for a shoutout? Get in touch.


Liked this post?

Check out these related articles that might be useful for you. They cover similar topics and provide additional insights.

Webdev
3 min read

Native Popover Element with HTML

Create overlays and dropdowns easily with the native HTML popover API

Jan 24, 2025
Read article
Webdev
13 min read

10 Essential Terminal Commands Every Developer Should Know

List of useful Unix terminal commands to boost your productivity. Here are some of my favorites.

Aug 21, 2024
Read article
Webdev
3 min read

HTML Details Element: The Native Accordion You're Not Using

Discover how the HTML details element can replace your JavaScript accordions and why it might be better than your current solution

Dec 10, 2024
Read article
Webdev
5 min read

Add Auth to Astro 5 with Clerk in 5 Minutes

The simplest setup for adding Clerk authentication to your Astro project, with minimal code

Dec 18, 2024
Read article
Webdev
8 min read

Become a Web Developer in 180 Days

A comprehensive roadmap to becoming a proficient web developer

Oct 29, 2019
Read article
Webdev
3 min read

Improve PageSpeed Insights Score with Lazy Loading Iframes

How to save bandwidth and speed up your site by lazy-loading iframes

Sep 13, 2024
Read article
Webdev
6 min read

Integrating Docker with React

Streamline your development and deployment processes

Jul 16, 2020
Read article
Webdev
12 min read

Robust Data Fetching Architecture For Complex React/Next.js Apps

How I use the 'Three Layers of Data' architecture pattern for React and Next.js apps to avoid common pitfalls, tech debt, and improve performance

May 4, 2025
Read article
Webdev
3 min read

scrollbar-width & scrollbar-gutter: CSS Properties for Layout Control

Prevent content shifts and refine scrollable UIs with scrollbar-width and scrollbar-gutter

Dec 19, 2024
Read article

This article was originally published on https://www.trevorlasn.com/blog/csp-headers-astro. It was written by a human and polished using grammar tools for clarity.