Security Headers: The HTTP Headers 90% of Websites Are Missing

Security Headers: The HTTP Headers 90% of Websites Are Missing

The cheapest security investment you are not making

Visit securityheaders.com and scan your company’s website. If you see anything below an A grade, you are missing basic security infrastructure that costs exactly zero euros to implement and prevents entire categories of attacks.

Security headers are HTTP response headers that instruct the browser how to handle your content. They are the digital equivalent of locking your front door, trivially easy, shockingly effective, and inexplicably ignored by the vast majority of websites. According to OWASP, missing security headers remain in the top 10 web application vulnerabilities, year after year.

The irony is that implementing them takes less time than reading this article. A properly configured Nginx, Apache, or Cloudflare setup can add all critical security headers in under 15 minutes.

The five headers every website must have

1. Strict-Transport-Security (HSTS)

HSTS tells the browser: “Never communicate with this domain over plain HTTP. Always use HTTPS.” Without HSTS, an attacker performing a man-in-the-middle attack on a coffee shop Wi-Fi can intercept the initial HTTP request before it redirects to HTTPS and inject malicious content.

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

The max-age=31536000 tells the browser to remember this policy for one year. The includeSubDomains directive applies it to all subdomains. The preload flag allows submission to the HSTS Preload List maintained by Chrome, which hardcodes your domain as HTTPS-only in the browser itself.

2. X-Frame-Options

This header prevents your website from being embedded in an <iframe> on another domain, the primary vector for clickjacking attacks. Without it, an attacker can overlay your login page with an invisible iframe and capture credentials.

X-Frame-Options: DENY

Use DENY to block all framing, or SAMEORIGIN to allow framing only from your own domain.

3. X-Content-Type-Options

Browsers historically attempted to “sniff” the MIME type of a resource, sometimes interpreting a text file as executable JavaScript. This header disables that dangerous behavior.

X-Content-Type-Options: nosniff

This is a single-value header with no configuration options. There is no reason to ever omit it.

4. Content-Security-Policy (CSP)

CSP is the most powerful and most complex security header. It defines a whitelist of content sources that the browser is allowed to load. A properly configured CSP makes XSS attacks virtually impossible because even if an attacker manages to inject a <script> tag, the browser refuses to execute it unless the source is explicitly whitelisted.

Content-Security-Policy: 
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  img-src 'self' data: https://media.example.com;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';

5. Referrer-Policy

Controls how much referrer information is sent when navigating away from your site. Without it, sensitive URL parameters (session tokens, internal paths) may leak to third-party sites.

Referrer-Policy: strict-origin-when-cross-origin

How we test: automated security verification

At x078, security headers are not a “nice to have”. they are a deployment gate. Every website we ship is validated by an automated Playwright test suite that runs before any deployment reaches production. The test verifies every critical header is present and correctly configured:

// Excerpt from our security test suite
test.describe('Security Headers', () => {
  test('response headers enforce security policies', async ({ request }) => {
    const response = await request.get('/');
    const headers = response.headers();

    const checks = [
      { header: 'x-frame-options', expected: /DENY|SAMEORIGIN/i, severity: 'critical' },
      { header: 'x-content-type-options', expected: /nosniff/i, severity: 'critical' },
      { header: 'referrer-policy', expected: /.+/, severity: 'warning' },
      { header: 'strict-transport-security', expected: /max-age=/, severity: 'critical' },
    ];

    for (const check of checks) {
      const value = headers[check.header];
      if (check.severity === 'critical') {
        expect(value).toBeTruthy();
        if (value) expect(value).toMatch(check.expected);
      }
    }
  });
});

This is not optional. This is not a manual checklist. It is a programmatic verification that runs on every build, every deployment, every environment. If a header is missing, the deployment fails. The Playwright suite also tests for:

  • Cookie security flags: Every cookie must have Secure, HttpOnly, and appropriate SameSite attributes
  • Error page information disclosure: 404 pages must not leak stack traces, framework versions, or internal file paths
  • HTTP method tampering: API endpoints must reject unexpected HTTP methods (PUT, DELETE, PATCH) with 405 responses

Server-level hardening

Beyond HTTP headers, our security audit tool performs comprehensive server-level checks on every HestiaCP-managed deployment:

# System hardening checks
v-security-audit --system         # OS & service hardening
v-security-audit --frontend URL   # External HTTP security scan
v-security-audit --pentest URL    # Offensive self-attack simulation
v-security-audit --all            # Full audit: system + backend + frontend + pentest

The system audit checks SSH configuration (key-only auth, no root login), firewall rules, service exposure, file permissions, and package update status. The frontend audit verifies headers, SSL configuration, and cookie policies. The pentest module runs automated attack simulations (XSS payloads, CRLF injection, path traversal attempts) against the live site to verify that defenses hold under adversarial conditions.

The 15-minute fix

If you are running Nginx, here is the complete configuration block that implements all five critical headers:

# Add to your server block in nginx.conf
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; frame-ancestors 'none';" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

For Cloudflare users, these can be set via Transform Rules in the dashboard without touching server configuration.

The investment is 15 minutes of configuration. The return is immunity to clickjacking, MIME-sniffing, protocol downgrade, and a significant reduction in XSS attack surface. There is no rational argument for not implementing them. Scan your site at securityheaders.com. If the grade is below A, the fix is waiting.

[ SYSTEM.FAQ ]

Frequently Asked Questions

What are security headers and why do they matter?

Security headers are HTTP response headers that instruct the browser to enforce specific security policies. They prevent common attacks like clickjacking (X-Frame-Options), MIME-type sniffing (X-Content-Type-Options), protocol downgrade attacks (Strict-Transport-Security), and cross-site scripting (Content-Security-Policy). They cost nothing to implement and prevent entire categories of attacks.

How do I check if my website has proper security headers?

Visit securityheaders.com and enter your domain. The tool scans your HTTP response headers and grades your site from A+ to F. Alternatively, open your browser's developer tools, visit your website, and check the Response Headers in the Network tab. Every response should include at minimum X-Frame-Options, X-Content-Type-Options, and Strict-Transport-Security.

Does Cloudflare automatically add security headers?

Cloudflare adds some headers by default (like basic HSTS if configured), but it does not automatically add X-Frame-Options, Content-Security-Policy, or Referrer-Policy. These must be explicitly configured either in your Cloudflare dashboard (Transform Rules) or in your origin server's response headers.

Can security headers break my website?

A misconfigured Content-Security-Policy (CSP) can block legitimate scripts, styles, or fonts, this is the most common issue. Start with CSP in report-only mode to identify violations before enforcing. X-Frame-Options, X-Content-Type-Options, and HSTS are safe to deploy immediately with no risk of breaking functionality.

> START_PROJECT

Need a website that earns trust, ranks in search, and gives your business a stronger digital presence? Start the conversation here.