Security9 min read

Lifting Your Security Headers Grade from D to A — A 30-Minute Checklist

Most websites score D or F on security headers — not because their stack is insecure but because nobody told them which headers to set. Six headers, four minutes each, A grade.

Enis Getmez avatarBy Enis GetmezFounder & Lead Engineer

Why most sites score D or F

If you run securityheaders.com or our HTTP Security Headers Grader against the top 1,000 small-business websites, roughly 70% will score D or F. Not because the sites are catastrophically insecure — most run on perfectly modern stacks. They score badly because the headers protect against attacks that need explicit opt-in from the site owner, and most owners never opt in.

Six headers, configured correctly, take a typical site from "F" to "A". Most are one-line additions to your nginx or Apache config. None require code changes. None have downside for a normal website.

This article walks through each one with the exact directive to add and the exact thing each one defends against.

Krawly HTTP Security Headers Grader — A-F grade with line-by-line analysis
Krawly HTTP Security Headers Grader — A-F grade with line-by-line analysis

1. Strict-Transport-Security (HSTS) — the biggest grade lift

What it does: tells browsers to always use HTTPS for your domain, even if a user types `http://` or clicks an old http link. Once a browser sees the header, it remembers — typically for a year — and refuses to make any non-HTTPS request to your site.

Why this matters: without HSTS, a user on a hostile network (coffee shop wifi, hotel) who types `yoursite.com` into the address bar makes a plain HTTP request first. The server redirects to HTTPS — but the initial request is in cleartext, and an attacker can intercept it before the redirect lands.

The directive:

```

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

```

In nginx:

```

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

```

In Apache:

```

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

```

For Cloudflare-fronted sites: SSL/TLS → Edge Certificates → HSTS → enable.

Caveat: once you ship HSTS, browsers remember it. If you ever need to roll back to HTTP, you can't — the browser refuses. Test thoroughly on a subdomain first. Most sites should be on HTTPS-only anyway in 2026.

2. X-Content-Type-Options: nosniff — easy win, no downside

What it does: tells the browser to trust the `Content-Type` header you send and not "sniff" the file content to guess the type.

Why this matters: without this header, a browser might decide that a file you served as `text/plain` looks like JavaScript and execute it as JS. If an attacker can upload a "txt" file that the browser auto-executes, that's a stored XSS.

The directive:

```

X-Content-Type-Options: nosniff

```

This has zero downside. Set it on every response. The "but my CMS serves files with wrong Content-Type" excuse means your CMS is wrong; fix it.

3. X-Frame-Options: SAMEORIGIN — clickjacking defense

What it does: prevents your site from being loaded inside an `