🎉 hey, I shipped skillcraft.ai It's like Reddit, but for tech courses

As a developer myself, I know how important it is to keep learning, which is why I created this community.

Published
3 min read

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.


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

Webdev
3 min read

CVE-2025-29927 - Next.js Middleware Bypass Explained In Simple Terms

The vulnerability skips Next.js middleware security checks by adding a single HTTP header

Apr 6, 2025
Read article
Webdev
3 min read

NPQ: Open source CLI tool that audits and protects your npm installs from malicious packages

A CLI tool that checks packages for security issues and social engineering attacks before they hit your project

Jul 26, 2025
Read article
Webdev
3 min read

CSS :has() - The Parent Selector We've Always Wanted

Transform your CSS with :has(), the game-changing selector that finally lets us style elements based on their children.

Dec 4, 2024
Read article
Webdev
3 min read

Form Validation That Doesn't Annoy Users: CSS :user-valid and :user-invalid

The new pseudo-classes :user-valid and :user-invalid give us a smarter way to style form validation states based on user interaction

Dec 12, 2024
Read article
Webdev
2 min read

link rel='modulepreload': Optimize JavaScript Module Loading

The rel='modulepreload' indicates that a module script should be fetched, parsed, and compiled preemptively, and stored for later execution

Dec 4, 2024
Read article
Webdev
4 min read

Self-Taught Developer's Guide to Thriving in Tech

How to turn your non-traditional background into your biggest asset

Sep 28, 2024
Read article
Webdev
14 min read

What's new in Next.js 16

Async params, Turbopack by default, and the cleanup of experimental features

Oct 25, 2025
Read article
Webdev
4 min read

Understanding Vue's Suspense

How the Suspense component manages async dependencies and improves loading states in Vue apps

Aug 23, 2024
Read article
Webdev
6 min read

Micro Frontends: The LEGO Approach to Web Development

Explore the concept of micro frontends in web development, understand their benefits, and learn when this architectural approach is most effective for building scalable applications.

Oct 2, 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.