Skip to content

_headers Validation Check

Overview

The _headers file contains critical security headers, especially the Content Security Policy (CSP) which restricts which external domains the app can load resources from or make API calls to.

As the codebase evolves and new external integrations are added, the CSP must be kept in sync. This validation script ensures that any external URLs/domains used in the source code are properly allowed in the CSP.

What It Does

The validation script (scripts/validate-headers.js):

  1. Scans source code for external URLs (http://, https://, ws://, wss://)
  2. Extracts domains from those URLs
  3. Verifies each domain is allowed in the CSP policy
  4. Reports missing domains that need to be added

Running the Check

Manual Check

bash
npm run validate:headers

Before Deployment

The check is automatically run as part of the validate script:

bash
npm run validate

This is executed before commits and deployments to prevent CSP violations.

CI & Deployment

Will CI Fail?

Yes, only for real production issues. The validation script uses an exclusion list to prevent false positives from:

  • Example/placeholder domains (example.com, domain.com, yourwebsite.com)
  • Seed data only (images.unsplash.com)
  • Backend/script-only domains (nominatim.openstreetmap.org)
  • Documentation examples (instagram.com, www.yelp.com, x.com)

Results:

  • ✓ Domains in CSP = Pass
  • ⊘ Excluded domains = Skipped (see scripts/validate-headers.js)
  • ✗ Missing production domains = Fail (must add to public/_headers)

Excluded Domains List

The exclusion list is maintained in scripts/validate-headers.js:

javascript
const EXCLUDED_DOMAINS = new Set([
  'example.com',
  'domain.com',
  'yourwebsite.com',
  'images.unsplash.com',
  'nominatim.openstreetmap.org',
  'github.com',
  'instagram.com',
  'www.google.com',
  'www.yelp.com',
  'yelp.com',
  'x.com',
  'wiki.openstreetmap.org',
  'api.openai.com',
  'docs.ourlantern.app',
  'corsproxy.io',
])

To add more exclusions: Edit this set directly in the script if you encounter legitimate false positives.


When to Update _headers

Update public/_headers when you:

  1. Add a new external API call

    • Example: integrating with a new analytics service
    • Add the domain to the appropriate CSP directive
  2. Add a new external script/style import

    • Example: loading fonts from a new CDN
    • Add the domain to script-src, style-src, or font-src
  3. Add a new image/media source

    • Example: pulling images from a new image service
    • Add the domain to img-src
  4. Add a webhook or callback URL

    • Add to connect-src or frame-src depending on usage

CSP Directives Reference

DirectivePurposeCommon Domains
connect-srcAPI calls, XHR, fetch, WebSocketFirebase, third-party APIs
script-srcJavaScript sourcesGoogle APIs, analytics
style-srcCSS sourcesFont services, CDNs
font-srcFont sourcesGoogle Fonts, type services
img-srcImage sourcesCDNs, image services
frame-srcIframe sourcesOAuth providers, embedded content

Current External Domains

In Use (Production)

  • *.googleapis.com - Google APIs (auth, services)
  • *.firebaseio.com - Firebase Realtime Database
  • *.cloudfunctions.net - Firebase Cloud Functions
  • api.bigdatacloud.net - Geolocation/IP lookup services
  • overpass-api.de - OpenStreetMap Overpass API
  • overpass.kumi.systems - Overpass API fallback
  • maps.mail.ru - Overpass API fallback
  • *.cloudflareaccess.com - Cloudflare Access (authentication)

In Seed/Test Data (Not Critical for CSP)

  • images.unsplash.com - Used in seed venue data only
  • example.com - Used in seed data placeholders

In Scripts Only (Not Frontend)

  • nominatim.openstreetmap.org - Used in backend import scripts
  • github.com - Not needed in CSP

Common Mistakes

Don't:

  • Hardcode URLs as strings to test domains that never get deployed
  • Add domains without understanding which CSP directive they belong in
  • Keep outdated domains in CSP if they're no longer used

Do:

  • Run validation before committing code that adds new external URLs
  • Update CSP with the specific domain, not just broad wildcards
  • Check if the domain might already be covered by an existing wildcard
  • Document why a domain is needed in the _headers file

Troubleshooting

Script reports false positives (test/example domains)

The script scans for ALL external URLs in source code, including:

  • Seed data (src/lib/seedVenues.js)
  • Test data and examples in source comments
  • Documentation examples

These don't necessarily need to be in CSP if they're never fetched in production.

For clarity, consider using example.com in seed data instead of real services.

Example false positives:

  • images.unsplash.com - Only used in src/lib/seedVenues.js
  • domain.com, yourwebsite.com - Example domains in comments
  • nominatim.openstreetmap.org - Only used in backend scripts, not frontend code

Real issues vs false positives

The script correctly identifies which domains are in CSP. Use this to determine if it's a real issue:

Real issue (needs CSP update):

  • Used in production code under src/
  • Used in client-side API calls
  • Required for frontend features

False positive (can be ignored):

  • Only in scripts/ directory
  • Only in seed/test data files
  • Only in documentation examples
  • Only in example comments
  • public/_headers - The actual CSP configuration (Cloudflare headers)
  • .storybook/static/_headers - Copy of headers for Storybook deployment
  • docs/engineering/deployment/app/DEPLOYMENT.md - Deployment guide with CSP details

Built with VitePress