Problem

Running a security scan against a static site hosted on Namecheap returned six missing headers:

  • `Strict-Transport-Security` — not set
  • `Content-Security-Policy` — not set
  • `X-Frame-Options` — not set
  • `X-Content-Type-Options` — not set
  • `Referrer-Policy` — not set
  • `Permissions-Policy` — not set

Missing security headers aren't theoretical risks on a static blog — but they are a fast fail on any professional security review, and the CSP gap in particular matters because without it, any injected script runs freely in the user's browser.

There was a second problem underneath the header issue: the site had inline (or ../script.js for posts in a subdirectory). Also fixed the create_post.py template so new posts generate clean.

Step 3 — Add security headers to .htaccess

Namecheap shared hosting runs Apache. Security headers go in .htaccess inside so the block only activates if mod_headers is loaded (it is, on Namecheap):



  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';"
  Header always set X-Frame-Options "DENY"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()"

What Each Header Does

Strict-Transport-Security — Tells browsers to always use HTTPS for this domain, even if the user types http://. The preload flag registers the domain in browser preload lists so first-time visitors also get HTTPS. max-age=31536000 is one year.

Content-Security-Policy — Defines exactly where the page can load resources from. default-src 'self' means only this domain. No CDNs, no inline scripts, no external fonts. If an attacker injects a