Skip to main content

Content Security Policy (CSP) Issues

If you're using nginx to serve your Docusaurus site and encountering Content Security Policy (CSP) errors, this guide will help you fix them.

Common CSP Errors

You might see errors like these in your browser console:

Content-Security-Policy: The page's settings blocked a script (script-src-elem)
Content-Security-Policy: The page's settings blocked the loading of a resource (img-src)
Content-Security-Policy: The page's settings blocked the loading of a resource (connect-src)

Understanding CSP

Content Security Policy is a security feature that helps prevent XSS attacks by controlling which resources can be loaded. However, it can also block legitimate external services used by your Docusaurus site.

Common External Services

Modern Docusaurus sites often use:

  • Analytics services for tracking
  • Widget services for donations/support
  • Search services for AI-powered search
  • Comment systems like Giscus for GitHub-based comments
  • SVG Data URIs for icons and graphics

Docusaurus CSP Configuration (GitHub Pages)

If you're deploying to GitHub Pages, you may encounter CSP issues because GitHub Pages sets strict CSP headers by default. You can configure CSP directly in your docusaurus.config.ts file:

Basic Giscus Comments Configuration

docusaurus.config.ts
const config: Config = {
title: 'Your Site Title',
// ... other config

// Content Security Policy configuration to allow Giscus comments
headTags: [
{
tagName: 'meta',
attributes: {
'http-equiv': 'Content-Security-Policy',
content: "default-src 'self'; frame-src 'self' https://giscus.app; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://giscus.app; style-src 'self' 'unsafe-inline' https://giscus.app; img-src 'self' data: https:; connect-src 'self' https://giscus.app https://api.github.com; font-src 'self' data:;",
},
},
],

// ... rest of your config
};

With Additional Services

docusaurus.config.ts - Multiple Services
headTags: [
{
tagName: 'meta',
attributes: {
'http-equiv': 'Content-Security-Policy',
content: "default-src 'self'; frame-src 'self' https://giscus.app; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://giscus.app https://cdnjs.buymeacoffee.com https://widget.buymeacoffee.com https://us-assets.i.posthog.com; style-src 'self' 'unsafe-inline' https://giscus.app; img-src 'self' data: https:; connect-src 'self' https://giscus.app https://api.github.com https://api.mendable.ai https://us.i.posthog.com; font-src 'self' data:;",
},
},
],

Common Giscus CSP Errors

If you see these errors for Giscus comments:

Content-Security-Policy: The page's settings blocked the loading of a resource (frame-src) at https://giscus.app/

Add these domains to your CSP:

  • frame-src: https://giscus.app (for the comment iframe)
  • script-src: https://giscus.app (for Giscus JavaScript)
  • style-src: https://giscus.app (for Giscus CSS)
  • connect-src: https://giscus.app https://api.github.com (for API calls)

Nginx CSP Configuration

Add these CSP headers to your nginx configuration to allow required external resources:

⚠️ Important: Use Single-Line Format

Multi-line CSP headers can cause 502 Bad Gateway errors. Always use single-line format:

Single-Line CSP Configuration (Recommended)
server {
listen 443 ssl;
http2 on;
server_name your-domain.com;

# Your existing SSL and other configurations...

# Content Security Policy - SINGLE LINE FORMAT
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://external-analytics-assets.com https://widget-service.com; img-src 'self' https://external-analytics.com data:; connect-src 'self' https://search-service.com https://analytics-api.com https://analytics-app.com; style-src 'self' 'unsafe-inline'; font-src 'self' data:; frame-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self';" always;

# Your existing location blocks...
location / {
# Your proxy configuration
}
}

Real-World Examples

PostHog Analytics Only

PostHog Analytics Example
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://us-assets.i.posthog.com https://cdnjs.buymeacoffee.com; img-src 'self' data:; connect-src 'self' https://api.mendable.ai https://us.i.posthog.com https://app.posthog.com; style-src 'self' 'unsafe-inline';" always;

With Google Fonts

If your site uses Google Fonts, add these domains:

PostHog + Google Fonts Example
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://us-assets.i.posthog.com https://cdnjs.buymeacoffee.com; img-src 'self' data:; connect-src 'self' https://api.mendable.ai https://us.i.posthog.com https://app.posthog.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:;" always;

Google Fonts requires two domains:

  • fonts.googleapis.com → CSS stylesheets (add to style-src)
  • fonts.gstatic.com → Font files (add to font-src)

Minimal CSP Configuration

For basic testing, use this minimal configuration:

Minimal CSP Configuration
# Add to your nginx server block
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://your-analytics-domain.com https://your-widget-domain.com; img-src 'self' data:; connect-src 'self' https://your-api-domain.com; style-src 'self' 'unsafe-inline';" always;

Directive Explanations

script-src

Controls which scripts can be executed:

  • 'self': Scripts from your own domain
  • 'unsafe-inline': Inline scripts (required by Docusaurus)
  • 'unsafe-eval': Dynamic code evaluation (required by some components)
  • External domains for analytics and widgets

img-src

Controls which images can be loaded:

  • 'self': Images from your own domain
  • data:: Data URIs for SVG icons and graphics

connect-src

Controls which URLs can be loaded using AJAX, WebSockets, etc.:

  • 'self': Your own domain
  • External services and analytics

Implementation Steps

  1. Identify your external services by checking browser console errors
  2. Update your nginx configuration with the appropriate domains
  3. Test the configuration:
    sudo nginx -t
    sudo systemctl reload nginx
  4. Verify functionality works as expected

Troubleshooting Tips

Configuration Not Working?

  1. Check nginx syntax:

    sudo nginx -t
  2. Verify headers are being sent:

    curl -I https://your-domain.com
  3. Check nginx error logs:

    sudo tail -f /var/log/nginx/error.log

Still Getting Errors?

If you're still seeing CSP errors after applying the configuration:

  1. Check for multiple CSP headers - only one should be present
  2. Ensure no conflicting CSP in your application
  3. Verify the domain names match exactly (check browser console for exact URLs)

502 Bad Gateway / Cloudflare Errors

If you get a white page with "Bad Gateway" or Cloudflare errors after adding CSP:

  1. Check nginx syntax:

    sudo nginx -t
  2. Use single-line CSP format (multi-line can cause HTTP protocol errors):

    # ❌ DON'T - Multi-line format
    add_header Content-Security-Policy "
    default-src 'self';
    script-src 'self';
    " always;

    # ✅ DO - Single-line format
    add_header Content-Security-Policy "default-src 'self'; script-src 'self';" always;
  3. Temporarily remove CSP to confirm nginx works:

    # Comment out CSP line and test
    sudo nginx -t && sudo systemctl reload nginx
  4. Start with minimal CSP and add domains gradually:

    add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data: https:;" always;

Multiple Domains for Same Service

Some services (like PostHog) use multiple domains:

  • Assets domain: us-assets.i.posthog.com (for scripts)
  • API domain: us.i.posthog.com (for data collection)
  • App domain: app.posthog.com (for events/tracking)

Add all required domains to avoid partial functionality.

Adding New External Services

When adding new external services to your Docusaurus site:

  1. Check browser console for CSP errors
  2. Identify the blocked domain from the error message
  3. Add the domain to the appropriate CSP directive
  4. Test thoroughly after making changes

Security Considerations

  • Use specific domains instead of wildcards when possible
  • Avoid 'unsafe-eval' if your site doesn't require it
  • Regularly review your CSP policy as you add new features
  • Test in multiple browsers to ensure compatibility
  • Monitor for new CSP violations in production

Common Domain Patterns

Replace the example domains in the configuration with your actual service domains:

  • Analytics: Usually have domains ending in analytics-related TLDs
  • CDN Services: Often use CDN-specific domain patterns
  • Widget Services: Typically have widget or button-related domains
  • Search Services: Usually have search or AI-related domain names
Buy me a beer


Hi, how can I help you?

Buy me a coffee