DEV Community

Cover image for What your site tells a stranger before it renders a single pixel
Mayank Jain
Mayank Jain

Posted on

What your site tells a stranger before it renders a single pixel

Type a domain, hit enter, and before anything paints, your server and the browser have already had a short conversation. The server sends back response headers — and to anyone who knows how to read them, those headers are a fairly candid statement about how seriously that site takes its own security.

Attackers read them first. Not because headers are exciting, but because they're free: no login, no exploit, nothing in your logs. One request tells them whether you're worth more attention.

Let's read them the way they do. Open devtools → Network → reload → click the first request → Response Headers. Follow along on your own site.

1. Strict-Transport-Security — does your HTTPS actually mean anything?

You have a cert. The padlock shows. But think about what happens when someone types your domain without the scheme — which is everyone:

GET http://yourdomain.com     ← plaintext, before your redirect exists
301 → https://yourdomain.com  ← too late for that first hop
Enter fullscreen mode Exit fullscreen mode

On a hostile network, an attacker in the middle can intercept that first request and simply never deliver your redirect, keeping the victim on plaintext they won't notice.

HSTS fixes it by telling the browser: for the next N seconds, never contact this host over HTTP at all.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Enter fullscreen mode Exit fullscreen mode

Reading it: no header → every first visit is interceptable. A max-age far under a year is a weak commitment. No includeSubDomains → protection stops at the apex. HTTP Archive's 2025 crawl found HSTS on about 36% of pages.

2. Content-Security-Policy — what happens when something does get injected?

The most consequential header, and the least deployed. CSP tells the browser which sources of script are allowed to execute. Anything else — an injected <script> from a comment field, a compromised third-party widget, a supply-chain hit on a dependency — the browser refuses to run.

Its absence isn't a vulnerability by itself. It's the absence of the safety net under every other mistake you might make. With a solid CSP, an XSS bug is often an annoyance. Without one, the same bug owns the page.

Same crawl: only 21.9% of sites send a CSP at all.

# what you want (nonce-based)
Content-Security-Policy: script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none'

# what mostly gets shipped
Content-Security-Policy: script-src 'self' 'unsafe-inline'
Enter fullscreen mode Exit fullscreen mode

Reading it: 'unsafe-inline' in script-src substantially undoes the protection — it permits exactly the inline execution injection relies on. A nonce or hash policy is the real thing. It's more work, which is why it's rarer.

One warning from our own production, since I've now paid for this lesson: if you go nonce-based on Next.js App Router, make sure every interactive page renders dynamically. A statically prerendered page has no request, so it gets no nonce, so the browser blocks every script on it. Dev never shows this — next dev renders everything dynamically.

3. Set-Cookie — how carefully is the session handled?

Your session cookie is the logged-in user. Three attributes decide how hard it is to steal:

Set-Cookie: session=…; HttpOnly; Secure; SameSite=Lax; Path=/
Enter fullscreen mode Exit fullscreen mode
  • HttpOnly — JavaScript can't read it. Without this, any script injection exfiltrates sessions directly.
  • Secure — never sent over plaintext.
  • SameSite — restricts cross-site sending; the core CSRF defence.

Reading it: a session cookie without HttpOnly tells an attacker that one XSS gets them accounts, not just defacement.

4. Server / X-Powered-By — what exactly are you running?

Plenty of stacks announce their software and version by default:

Server: Apache/2.4.41
X-Powered-By: PHP/7.4.3
Enter fullscreen mode Exit fullscreen mode

That's a shortcut: instead of probing, they look up known vulnerabilities for that exact build. Removing these isn't a real defence — a determined attacker fingerprints you anyway — but publishing them narrows their work from hours to seconds, and a version string also announces, at a glance, whether you're years behind.

The meta-signal

Here's the part that matters more than any single header. Someone reading your response isn't only collecting weaknesses — they're forming a judgement about the people who run this site. These headers are cheap; most are one line of config. A site with HSTS, a real CSP and properly flagged cookies says someone here thought about this, and probably thought about the harder things too. A site with none of them says the opposite, before any deeper probing begins.

Your five-minute checklist

Devtools open, first request selected, four questions:

  1. Is Strict-Transport-Security present, with a long max-age?
  2. Is there a Content-Security-Policy — and does it avoid unsafe-inline for scripts?
  3. Does the session cookie carry HttpOnly, Secure and SameSite?
  4. Are you advertising exact software versions you don't need to?

Whatever you find is the same thing a stranger sees on their first request. The only difference is that they've already looked.


Disclosure: I work on Webcuris — these headers are among the first things we read on a scan, along with TLS, email auth and exposed subdomains. But you don't need us for the checklist above; the devtools you already have will answer all four questions.

Originally published at webcuris.com.

Top comments (0)