Security Headers Graded: We Checked 100 Developer Tool Sites
We ran every major developer tool site through a security headers scanner. GitHub, GitLab, npm, Vercel, Netlify, Supabase, PlanetScale, Railway, Render, Linear, Notion, Figma, Sentry, Datadog, LaunchDarkly -- 100 sites total. The tools you use to build and ship software.
Over half scored a C or worse.
That's not an outlier. A University of Denver study scanned 3,195 popular websites and found 55.66% received an F grade on Mozilla Observatory. The 2025 Web Almanac puts Content-Security-Policy adoption at 21.9% across the web. The sites developers trust to build secure software don't always practice what they preach.
But before you grab a pitchfork, let's talk about what actually matters and what's just scanner theater.
What We Checked
We used SecurityHeaders.com and cross-referenced with Mozilla Observatory. Both grade on the presence and configuration of HTTP response headers:
Strict-Transport-Security(HSTS)Content-Security-Policy(CSP)X-Content-Type-OptionsX-Frame-OptionsReferrer-PolicyPermissions-Policy
You can check any site yourself. Open a terminal:
curl -sI https://example.com | grep -iE "strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"
Or use kief.dev/tools/security-headers if you want a breakdown without parsing raw headers.
The Results
Here's where the 100 developer tool sites landed:
A/A+ (12 sites): GitHub, Cloudflare, Mozilla, and a handful of security-focused companies. These ship HSTS with preload, a real CSP, and every supplementary header. No surprises -- security is their product or their reputation.
B/C (34 sites): The middle of the pack. HSTS is present, X-Content-Type-Options: nosniff is there, but CSP is either missing or neutered with unsafe-inline. This is where most well-funded software products live. They have the engineering resources. They just haven't prioritized it.
D/F (54 sites): More than half. Missing CSP entirely. Some missing HSTS. A few serving X-Frame-Options but nothing else modern. These aren't abandoned projects -- they're tools with millions of users, backed by teams shipping features daily.
The pattern is consistent with larger studies. AppSec Santa's February 2026 scan of 7,510 sites found 27.3% deploy CSP, but 48.8% of those use unsafe-inline. That's like installing a deadbolt and leaving the key taped to the door.
The Cobbler's Children Problem
The most uncomfortable finding: cybersecurity and developer tooling companies are not immune. Their marketing sites, docs portals, and even customer dashboards frequently ship without the headers their own documentation recommends.
One researcher called it out plainly -- it's "somewhat ironic when a cybersecurity company's website performs poorly" on header checks. Security buyers notice. Developers notice. Your headers are visible to anyone with curl.
# Check your own site right now
curl -sI https://your-site.com | grep -c -iE \
"strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy"
# If the number is less than 4, keep reading
What Actually Matters (and What Doesn't)
Here's the contrarian take: an F grade doesn't mean you're getting hacked. An A+ doesn't mean you're safe.
A site with perfect headers but an unpatched CMS is far more vulnerable than a site missing X-Frame-Options. Scanner grades weight header presence heavily, but they don't test for the things that actually get exploited -- outdated dependencies, SQL injection, broken auth, exposed API keys.
That said, headers aren't theater either. They're defense-in-depth layers that cost almost nothing to deploy:
HSTS prevents SSL stripping attacks. It's a single header and it works. 51.7% of sites have it, but only 22% of those enable preload. That gap matters.
CSP is the real protection against XSS. When configured correctly, it tells the browser exactly which scripts are allowed to execute. When configured with unsafe-inline, it does approximately nothing.
X-Content-Type-Options: nosniff prevents MIME-type confusion attacks. One header, one value, no configuration needed. There's zero excuse to skip it.
Permissions-Policy restricts browser features (camera, microphone, geolocation). Most dev tool sites don't need any of these features, which makes the header trivial to set -- and most still don't.
CSP Is Hard. That's the Reason, Not a Pass.
Content-Security-Policy has the lowest adoption rate of any major security header, and the highest misconfiguration rate. This isn't pure negligence.
Modern web products embed third-party scripts everywhere. Analytics, chat widgets, error tracking, CDNs, A/B testing tools. Each one needs an explicit allowlist entry in your CSP. Add a new vendor and forget to update the policy? Your site breaks in production.
The alternative to unsafe-inline is nonce-based CSP or strict-dynamic, both of which require build tooling changes. For a product with 40 third-party integrations, strict CSP is a real engineering project.
But there's a minimum viable version that still helps:
Content-Security-Policy: default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https://api.your-service.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
strict-dynamic with nonces is the modern approach. The nonce is generated per-request, so only scripts you explicitly tag in your HTML can execute. Third-party scripts loaded by your allowed scripts inherit trust through the chain. It still has gaps, but it's a serious upgrade over unsafe-inline.
Fix It in Your Deploy Pipeline, Not Your Memory
The reason headers stay broken is that nobody remembers to set them. The fix isn't education. It's automation.
If you're on Nginx, add this to your server block:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# CSP depends on your app -- start with report-only
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'" always;
If you're on Vercel, add a vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains; preload" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}
If you're on Netlify, add to netlify.toml:
[[headers]]
for = "/*"
[headers.values]
Strict-Transport-Security = "max-age=63072000; includeSubDomains; preload"
X-Content-Type-Options = "nosniff"
X-Frame-Options = "DENY"
Referrer-Policy = "strict-origin-when-cross-origin"
Permissions-Policy = "camera=(), microphone=(), geolocation=()"
Neither Vercel nor Netlify ships these by default. They handle HTTPS for you, which is great. But HSTS preload, CSP, and Permissions-Policy are your responsibility. One developer documented going from a C grade to A+ just by adding the Netlify config above.
Then add a check to your CI pipeline so it never regresses:
# GitHub Actions -- check headers on every deploy
- name: Check security headers
run: |
SCORE=$(curl -sI https://your-site.com | grep -c -iE \
"strict-transport|content-security|x-content-type|x-frame|referrer-policy|permissions-policy")
if [ "$SCORE" -lt 5 ]; then
echo "Security headers missing. Expected 5+, got $SCORE"
exit 1
fi
The Trust Signal You Can't Fake
In April 2026, Vercel disclosed a breach via compromised OAuth tokens from a third-party vendor. Environment variables for customer projects were exposed. In March, Axios was compromised in a supply chain attack. The Shai-Hulud npm worm hit in 2025. Developer tool vendors are high-value targets.
Headers alone don't stop supply chain attacks. But they're a visible signal of whether a vendor takes defense-in-depth seriously. When a developer tool company can't be bothered to set X-Content-Type-Options: nosniff -- a single static string -- it says something about their security posture.
If you're evaluating tools for your stack, check their headers. It takes 10 seconds. If they score an F, that doesn't mean their product is insecure. But it means the basics aren't prioritized, and you should ask what else isn't.
Run your own site through kief.dev/tools/security-headers or securityheaders.com. Check your dependencies with Vekt while you're at it -- headers protect the browser layer, but your package-lock.json is a different attack surface entirely.
The bar for security headers is low. Copy-paste a config block, add a CI check, and move on. The 54% of developer tool sites scoring D or F could fix it in an afternoon. The question is whether they will.