🎉 hey, I shipped skillcraft.ai Career Intelligence for Developers

Automation-proof your career. See what's rising, what's dying, and where the jobs are going.

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

Native Popover Element with HTML

Create overlays and dropdowns easily with the native HTML popover API

Jan 24, 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

CSS ::target-text for Text Highlighting

A look at how browsers can highlight text fragments using CSS ::target-text, making text sharing and navigation more user-friendly

Dec 17, 2024
Read article
Webdev
7 min read

How to Land Your First Tech Job

A developer's guide to tech interviews - from someone who sits on both sides of the table

Oct 24, 2024
Read article
Webdev
36 min read

IndexNow: Get your content indexed instantly by AI search engines and traditional search

Stop waiting weeks for crawlers. Learn how to notify Bing, DuckDuckGo, ChatGPT, and Perplexity instantly when you publish new content using the free IndexNow protocol

Oct 27, 2025
Read article
Webdev
3 min read

CSS Supports Nesting Now

CSS nesting is finally supported in all major browsers. Write cleaner, organized stylesheets without Sass or Less

Dec 6, 2024
Read article
Webdev
3 min read

CSS @supports: Write Future-Proof CSS

Detect CSS feature support and provide smart fallbacks with @supports

Dec 6, 2024
Read article
Webdev
3 min read

The HTML Native Search Element

The search HTML element is a container that represents the parts of the web page with search functionality

Dec 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.