VacciChain implements comprehensive security headers to protect against common web vulnerabilities including XSS (Cross-Site Scripting), clickjacking, MIME sniffing, and other attacks. This is especially critical for a blockchain application that handles wallet interactions and sensitive health data.
Purpose: Prevents XSS attacks by controlling which resources can be loaded and executed.
Frontend Configuration (Nginx):
Content-Security-Policy: default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' data:;
connect-src 'self' https://horizon-testnet.stellar.org https://soroban-testnet.stellar.org https://horizon.stellar.org https://soroban.stellar.org;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
Backend Configuration:
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'
Why This Matters for VacciChain:
- Prevents malicious scripts from intercepting Freighter wallet signing prompts
- Blocks unauthorized connections to external APIs
- Protects against injection attacks that could steal vaccination records
Production Notes:
unsafe-inlineis used for React inline styles in development- Consider using a CSS-in-JS solution or nonces to remove
unsafe-inlinein production connect-srcexplicitly allows Stellar Horizon and Soroban RPC endpoints
Value: DENY
Purpose: Prevents clickjacking attacks by disallowing the page to be embedded in frames/iframes.
Why This Matters for VacciChain:
- Prevents attackers from overlaying fake UI elements on top of wallet signing prompts
- Protects against UI redressing attacks that could trick users into signing malicious transactions
Value: nosniff
Purpose: Prevents browsers from MIME-sniffing responses, forcing them to respect the declared Content-Type.
Why This Matters for VacciChain:
- Prevents browsers from interpreting JSON responses as HTML/JavaScript
- Blocks attacks where malicious content is disguised with incorrect MIME types
Value: strict-origin-when-cross-origin
Purpose: Controls how much referrer information is sent with requests.
Behavior:
- Same-origin requests: Full URL is sent
- Cross-origin requests: Only origin (no path/query) is sent
- HTTPS → HTTP: No referrer is sent
Why This Matters for VacciChain:
- Prevents leaking sensitive URLs (e.g., with patient IDs) to external sites
- Maintains privacy while allowing legitimate analytics
Value: 1; mode=block
Purpose: Enables browser's built-in XSS filter (legacy, but still useful for older browsers).
Note: Modern browsers rely on CSP, but this provides defense-in-depth for older browsers.
Value: max-age=31536000; includeSubDomains; preload
Purpose: Forces browsers to only connect via HTTPS.
Status:
⚠️ Disabled in development (commented out innginx.conf)- ✅ Enabled in production (
nginx.production.conf)
Why This Matters for VacciChain:
- Prevents man-in-the-middle attacks
- Protects wallet private keys and authentication tokens in transit
- Critical for mainnet deployment
Production Deployment:
- Ensure HTTPS is working properly
- Test with a short
max-agefirst (e.g., 300 seconds) - Gradually increase to 31536000 (1 year)
- Consider HSTS preloading: https://hstspreload.org/
Value: geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()
Purpose: Disables unnecessary browser features to reduce attack surface.
Why This Matters for VacciChain:
- VacciChain doesn't need geolocation, camera, or other device features
- Reduces risk of permission-based attacks
- Improves privacy
Development: frontend/nginx.conf
- Includes
unsafe-inlinefor React development - HSTS disabled
- Suitable for local development and testnet
Production: frontend/nginx.production.conf
- Stricter CSP (no
unsafe-inline) - HSTS enabled
- Use for mainnet deployment
Middleware: backend/src/middleware/securityHeaders.js
- Applied to all API responses
- Restrictive CSP for JSON-only API
- Automatically loaded in
app.js
Linux/macOS:
chmod +x scripts/test-security-headers.sh
./scripts/test-security-headers.shWindows:
.\scripts\test-security-headers.ps1Custom URLs:
# Linux/macOS
./scripts/test-security-headers.sh https://staging.vaccichain.com https://api.vaccichain.com
# Windows
.\scripts\test-security-headers.ps1 -FrontendUrl "https://staging.vaccichain.com" -BackendUrl "https://api.vaccichain.com"Using curl:
# Frontend
curl -I http://localhost:3000
# Backend
curl -I http://localhost:4000/healthUsing browser DevTools:
- Open VacciChain in browser
- Open DevTools (F12)
- Go to Network tab
- Refresh page
- Click on the main document request
- Check "Response Headers" section
SecurityHeaders.com:
- Deploy to a publicly accessible URL
- Visit https://securityheaders.com/
- Enter your URL
- Target: Grade A or higher
Mozilla Observatory:
- Visit https://observatory.mozilla.org/
- Enter your URL
- Target: A+ rating
Expected Results:
- ✅ Content-Security-Policy: Present
- ✅ X-Frame-Options: DENY
- ✅ X-Content-Type-Options: nosniff
- ✅ Referrer-Policy: strict-origin-when-cross-origin
- ✅ Permissions-Policy: Present
⚠️ Strict-Transport-Security: Only in production with HTTPS
Symptom: Console errors like "Refused to execute inline script"
Solution:
- Move inline scripts to external
.jsfiles - Use nonces or hashes for necessary inline scripts
- For React: Use styled-components or CSS modules instead of inline styles
Symptom: Images, fonts, or API calls fail to load
Solution:
- Add the domain to the appropriate CSP directive
- Example:
img-src 'self' https://trusted-cdn.com - Be specific - avoid using wildcards like
*
Symptom: Wallet connection or signing fails
Solution:
- Ensure
connect-srcincludes Stellar endpoints - Check browser console for CSP violations
- Freighter injects scripts - may need
script-srcadjustments
Symptom: Browser forces HTTPS on localhost
Solution:
- Clear HSTS settings in browser:
- Chrome:
chrome://net-internals/#hsts→ Delete domain - Firefox: Delete
SiteSecurityServiceState.txtin profile folder
- Chrome:
- Use different domain for development (e.g.,
local.vaccichain.test)
- Test headers after every deployment
- Run security scanners monthly
- Review CSP violations in browser console
Consider adding CSP reporting in production:
add_header Content-Security-Policy "...; report-uri /csp-report";- Test in staging first
- Use
Content-Security-Policy-Report-Onlyto test without blocking - Monitor for violations before enforcing
- Review OWASP recommendations: https://owasp.org/www-project-secure-headers/
- Follow Mozilla guidelines: https://infosec.mozilla.org/guidelines/web_security
- Update headers as new threats emerge
- Switch to
nginx.production.conf - Enable HTTPS with valid SSL certificate
- Test HSTS with short
max-agefirst - Remove
unsafe-inlinefrom CSP if possible - Test all functionality (especially Freighter wallet)
- Run securityheaders.com scan (target: Grade A)
- Run Mozilla Observatory scan (target: A+)
- Set up CSP violation reporting
- Document any CSP exceptions and why they're needed
- Schedule regular security header audits
- OWASP Secure Headers Project
- MDN Web Security
- Content Security Policy Reference
- SecurityHeaders.com
- Mozilla Observatory
- HSTS Preload
For security concerns or questions:
- Review this documentation
- Check browser console for CSP violations
- Test with provided scripts
- Contact the security team for production deployments