Security Score 0/100 — Which Headers to Add

A quick guide to adding all 7 security headers to your web server.

troubleshooting

Security Score 0/100 — Which Headers to Add

A security score of 0/100 means your site is missing all recommended HTTP security headers. These headers protect your visitors from cross-site scripting (XSS), clickjacking, MIME sniffing attacks, and more. The good news: adding them takes about 10 minutes.

The 7 Security Headers You Need

Header What It Does
Content-Security-Policy Controls which resources the browser is allowed to load
Strict-Transport-Security Forces HTTPS for all future visits
X-Content-Type-Options Prevents MIME type sniffing
X-Frame-Options Prevents your site from being embedded in iframes (clickjacking)
Referrer-Policy Controls how much URL info is sent to other sites
Permissions-Policy Restricts browser features (camera, microphone, geolocation)
X-XSS-Protection Legacy XSS filter (still expected by scanners)

Priority: What to Add First

Start with the highest-impact, lowest-risk headers:

  1. Strict-Transport-Security — Zero risk if you already use HTTPS. Maximum impact.
  2. X-Content-Type-Options — One line, no configuration needed, no side effects.
  3. X-Frame-Options — Unless your site is intentionally embedded in iframes.
  4. Referrer-Policy — Low risk with strict-origin-when-cross-origin.
  5. Permissions-Policy — Restrict features you don't use.
  6. Content-Security-Policy — Highest protection but requires careful testing.
  7. X-XSS-Protection — Legacy, but easy to add.

Warning: A badly configured Content-Security-Policy can break your site. Start with Content-Security-Policy-Report-Only to test without blocking anything.

Complete Nginx Configuration

Add this inside your server block in your nginx config:

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-XSS-Protection "1; mode=block" always;

# Start with report-only CSP, then switch to enforcing
# add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" always;

# Enforcing CSP (uncomment when ready)
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" always;

Then reload nginx:

sudo nginx -t && sudo systemctl reload nginx

Complete Apache Configuration

Add this to your .htaccess file or virtual host config:

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';"
</IfModule>

Make sure mod_headers is enabled:

sudo a2enmod headers
sudo systemctl reload apache2

Customizing Content-Security-Policy

The CSP above is strict. Most real sites need to allow external resources. Common additions:

Google Analytics:

script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
img-src 'self' data: https://www.google-analytics.com;
connect-src 'self' https://www.google-analytics.com;

Google Fonts:

style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;

YouTube embeds:

frame-src https://www.youtube.com;

Tip: Open your browser console after adding CSP. Any blocked resource will show a clear error message telling you exactly what directive to update.

Testing Your Headers

After adding headers, verify them:

From the command line:

curl -I https://example.com

Look for each header in the response.

Online tools: - securityheaders.com — Gives you a letter grade (A+ is the goal) - observatory.mozilla.org — More detailed analysis from Mozilla

Tip: After adding all headers, re-run your SiteWatch security scan to see your updated score. Going from 0 to 80+ is entirely realistic with the configuration above.

Common Mistakes

  • Adding headers in the wrong location: In nginx, add_header in a location block overrides headers set in the server block. Use the always parameter.
  • Forgetting includeSubDomains on HSTS: Without it, subdomains remain vulnerable.
  • Too-strict CSP breaking the site: Always test with Content-Security-Policy-Report-Only first.
  • Not reloading the web server: Headers won't take effect until you reload.
SiteWatch detects and alerts you about this problem automatically.
14-day free trial. No credit card required.
Want SiteWatch to monitor this automatically?
All 10 monitors activate the moment you add a site. No configuration needed.
Start free trial
SiteWatch
Start free trial →