Top 5 Security Header Mistakes We See in SaaS Applications
After analyzing scan data from thousands of SaaS applications, clear patterns emerge. The same five security header misconfigurations appear again and again — and every one of them is fixable in under 10 minutes.
1. Missing Strict-Transport-Security (HSTS)
What it does: Forces browsers to only connect over HTTPS, preventing protocol downgrade attacks and cookie hijacking. How often we see it missing: ~45% of scanned SaaS apps The fix:Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Set max-age to at least one year (31536000 seconds). The includeSubDomains directive protects all subdomains. preload allows your domain to be hardcoded into browsers' HSTS lists.
2. No Content-Security-Policy (CSP)
What it does: Controls which resources the browser can load, preventing XSS attacks and data injection. How often we see it missing: ~62% of scanned SaaS apps The fix (starter policy):Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com
Start restrictive and loosen as needed. Use report-uri or report-to to catch violations without breaking your app.
3. Missing X-Frame-Options
What it does: Prevents your app from being embedded in iframes, blocking clickjacking attacks. How often we see it missing: ~38% of scanned SaaS apps The fix:X-Frame-Options: DENY
Use DENY unless your app specifically needs to be embedded (in which case, use SAMEORIGIN).
4. X-Content-Type-Options Not Set
What it does: Prevents browsers from MIME-sniffing a response away from the declared content type, blocking drive-by download attacks. How often we see it missing: ~35% of scanned SaaS apps The fix:X-Content-Type-Options: nosniff
One line. No configuration. No reason not to have it.
Why it matters for compliance: Required by SOC 2 and maps to OWASP A05:2021.5. Permissive or Missing Referrer-Policy
What it does: Controls how much referrer information is sent with requests, preventing URL-based data leakage. How often we see it missing or misconfigured: ~55% of scanned SaaS apps The fix:Referrer-Policy: strict-origin-when-cross-origin
This sends the origin (not the full URL) when navigating cross-origin, and sends the full URL for same-origin requests.
Why it matters for compliance: Maps to GDPR data minimization requirements and SOC 2 CC6.1.The 10-Minute Fix
If you're running a Node.js/Express app, add all five in one middleware:
app.use((req, res, next) => {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
res.setHeader('Content-Security-Policy', "default-src 'self'");
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});
For Nginx, add these to your server block. For Cloudflare, use Transform Rules. For Vercel or Netlify, add a headers config file.