_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):
- Scans source code for external URLs (http://, https://, ws://, wss://)
- Extracts domains from those URLs
- Verifies each domain is allowed in the CSP policy
- Reports missing domains that need to be added
Running the Check
Manual Check
npm run validate:headersBefore Deployment
The check is automatically run as part of the validate script:
npm run validateThis 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:
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:
Add a new external API call
- Example: integrating with a new analytics service
- Add the domain to the appropriate CSP directive
Add a new external script/style import
- Example: loading fonts from a new CDN
- Add the domain to
script-src,style-src, orfont-src
Add a new image/media source
- Example: pulling images from a new image service
- Add the domain to
img-src
Add a webhook or callback URL
- Add to
connect-srcorframe-srcdepending on usage
- Add to
CSP Directives Reference
| Directive | Purpose | Common Domains |
|---|---|---|
connect-src | API calls, XHR, fetch, WebSocket | Firebase, third-party APIs |
script-src | JavaScript sources | Google APIs, analytics |
style-src | CSS sources | Font services, CDNs |
font-src | Font sources | Google Fonts, type services |
img-src | Image sources | CDNs, image services |
frame-src | Iframe sources | OAuth providers, embedded content |
Current External Domains
In Use (Production)
*.googleapis.com- Google APIs (auth, services)*.firebaseio.com- Firebase Realtime Database*.cloudfunctions.net- Firebase Cloud Functionsapi.bigdatacloud.net- Geolocation/IP lookup servicesoverpass-api.de- OpenStreetMap Overpass APIoverpass.kumi.systems- Overpass API fallbackmaps.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 onlyexample.com- Used in seed data placeholders
In Scripts Only (Not Frontend)
nominatim.openstreetmap.org- Used in backend import scriptsgithub.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 insrc/lib/seedVenues.jsdomain.com,yourwebsite.com- Example domains in commentsnominatim.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
Related Files
public/_headers- The actual CSP configuration (Cloudflare headers).storybook/static/_headers- Copy of headers for Storybook deploymentdocs/engineering/deployment/app/DEPLOYMENT.md- Deployment guide with CSP details