Best practices for deploying Bengal sites securely. Since Bengal generates static files, most security concerns relate to HTTP headers, content policies, and build hygiene.
Security Headers
Configure your hosting platform to send security headers with every response.
Recommended Headers
| Header | Purpose |
|---|---|
Content-Security-Policy |
Prevents XSS and injection attacks |
X-Frame-Options |
Prevents clickjacking |
X-Content-Type-Options |
Prevents MIME-type sniffing |
Referrer-Policy |
Controls referrer information |
Permissions-Policy |
Restricts browser features |
Strict-Transport-Security |
Enforces HTTPS |
Platform Configuration
Createnetlify.tomlin your project root:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Createvercel.jsonin your project root:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
Create_headersin your output directory (or configure viapublic/_headers):
1 2 3 4 5 6 | |
Add to your server block:
1 2 3 4 5 6 7 8 | |
Add to.htaccessor server config:
1 2 3 4 5 6 7 | |
Content Security Policy (CSP)
The Content-Security-Policy header is your primary defense against XSS attacks.
Base Policy
Start with a restrictive policy and add exceptions as needed:
1 2 3 4 5 6 7 | |
Common Additions
| Need | Add to CSP |
|---|---|
| Inline styles | style-src 'self' 'unsafe-inline' |
| Inline scripts | script-src 'self' 'unsafe-inline'(avoid if possible) |
| Google Fonts | font-src 'self' fonts.gstatic.com; style-src 'self' fonts.googleapis.com |
| Google Analytics | script-src 'self' www.googletagmanager.com; connect-src www.google-analytics.com |
| Plausible | script-src 'self' plausible.io; connect-src plausible.io |
| External images | img-src 'self' data: https: |
| YouTube embeds | frame-src www.youtube-nocookie.com www.youtube.com |
| Vimeo embeds | frame-src player.vimeo.com |
| CodePen embeds | frame-src codepen.io |
| CodeSandbox embeds | frame-src codesandbox.io |
| StackBlitz embeds | frame-src stackblitz.com |
| GitHub Gist | script-src 'self' gist.github.com |
| Asciinema | script-src 'self' asciinema.org |
Testing CSP
Use the browser console to identify CSP violations:
- Open DevTools (F12)
- Go to the Console tab
- Look for CSP violation errors
- Adjust your policy as needed
Build Hygiene
Exclude Sensitive Files
Ensure sensitive files don't end up in your output:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Verify Before Deploy
Run validation before deploying:
1 2 3 4 5 6 7 8 | |
CI/CD Validation
Add security checks to your CI pipeline:
1 2 3 4 5 6 7 8 9 10 11 | |
Third-Party Scripts
Subresource Integrity (SRI)
When loading external scripts, use SRI to verify integrity:
1 2 3 4 5 | |
Generate SRI hashes:
1 2 3 4 5 | |
Self-Host When Possible
Bengal's asset fingerprinting provides cache-busting without CDN dependencies:
1 2 3 | |
Benefits of self-hosting:
- No third-party dependencies
- No tracking via CDN
- Full control over updates
- Works offline
HTTPS Enforcement
Verify baseurl
Ensure your configuration uses HTTPS:
1 2 3 | |
HSTS Header
Enable HTTP Strict Transport Security:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Warning
Only enable HSTS after confirming HTTPS works correctly. HSTS is cached by browsers and difficult to undo.
Media Embed Security
Bengal's media directives ({youtube},{vimeo},{gist}, etc.) include built-in security protections:
Input Validation
All embed IDs and paths are validated:
| Directive | Validation |
|---|---|
{youtube} |
11-character alphanumeric ID only |
{vimeo} |
Numeric ID only |
{gist} |
username/hashformat only |
{figure} |
Safe paths, no../traversal |
{video}/{audio} |
Extension whitelist |
Malicious inputs are rejected with clear error messages:
1 2 3 | |
Renders as an error block, not an embed.
Privacy by Default
External embeds use privacy-respecting modes:
- YouTube: Uses
youtube-nocookie.comby default - Vimeo: Enables Do Not Track (
dnt=1) by default
Iframe Sandboxing
External iframes include restricted sandbox attributes to limit capabilities.
CSP for Media Embeds
If using media embeds, add these frame sources to your CSP:
1 2 | |
Or selectively based on which directives you use.
Dependency Security
Audit Python Dependencies
1 2 3 4 5 6 7 8 9 10 | |
Keep Dependencies Updated
1 2 3 4 5 | |
Draft Protection
Drafts are excluded from production by default. Verify this works:
Check Configuration
1 2 3 | |
Verify Output
1 2 3 4 5 6 | |
CI Check
1 2 3 4 5 6 7 | |
Security Checklist
Before deploying to production:
Headers
- Content-Security-Policy configured
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Referrer-Policy set
- HSTS enabled (if HTTPS confirmed working)
Build
- Sensitive files excluded from build
- No API keys or secrets in content
- Drafts excluded from production
- Validation passes (
bengal validate --strict) - Links checked (
bengal health linkcheck)
Dependencies
- Dependencies audited for vulnerabilities
- Bengal and dependencies up to date
- SRI used for external scripts
Configuration
- baseurl uses HTTPS
- No debug settings in production config
- Environment-specific configs reviewed
Reporting Security Issues
Found a security vulnerability in Bengal?
Do NOT open a public GitHub issue.
Email security concerns to: security@bengal.dev
We'll respond within 48 hours and work with you on a fix before public disclosure.
Seealso
- Deployment Guide
- CI/CD Setup
- Configuration Reference
- Mozilla Observatory — Test your site's security headers