Six Security Headers Every Web Application Needs — and How to Check Yours

Run an automated web application scan against almost any system that hasn't had a dedicated security review, and you will find missing HTTP security headers. Consistently. Across sectors, across tech stacks, across applications built last year and applications built a decade ago.

This isn't a niche finding. It's one of the most common results we see in web application assessments — and it's one of the most fixable. Most security headers require a single line of configuration. The gap between a misconfigured application and a correctly hardened one is often an afternoon of work.

Here are the six you need to know, what they do, and how to check whether your application has them set correctly.

1. Content Security Policy (CSP)

CSP is a browser instruction that tells the browser which sources are allowed to load content on a page — scripts, stylesheets, images, fonts, frames. Without it, the browser will load content from any source, which means a successful XSS attack can load malicious scripts from an attacker-controlled server.

A CSP header restricts this. A minimal policy might look like:

Content-Security-Policy: default-src 'self'; script-src 'self'

This tells the browser to only load content from the same origin as the page. External scripts, inline scripts, and eval are all blocked unless explicitly permitted. Getting CSP right requires some iteration — overly strict policies break legitimate functionality — but even a permissive CSP is substantially better than none at all.

CSP also supports a report-uri or report-to directive, which sends violation reports to an endpoint you specify. This is valuable: you can deploy a CSP in report-only mode first (Content-Security-Policy-Report-Only), monitor what would have been blocked, and tighten the policy without breaking anything.

2. X-Frame-Options

This header controls whether the page can be embedded in an <iframe> on another site. Without it, an attacker can create a page that embeds your application in a hidden iframe and overlay it with a transparent element — a technique called clickjacking — tricking users into clicking on buttons or links they can't see.

The fix is one line:

X-Frame-Options: DENY

or, if you need to allow framing from the same origin:

X-Frame-Options: SAMEORIGIN

Note that CSP's frame-ancestors directive provides more granular control and is the modern approach — but X-Frame-Options has broader browser support and should be included for compatibility.

3. HTTP Strict Transport Security (HSTS)

HSTS tells browsers that the site should only ever be accessed over HTTPS. Without it, a user typing your domain without specifying HTTPS will initially connect over HTTP — leaving a window for a man-in-the-middle attacker to intercept and downgrade the connection before the redirect to HTTPS occurs.

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

The max-age value specifies how long (in seconds) the browser should remember to enforce HTTPS. One year (31,536,000 seconds) is standard. includeSubDomains extends the policy to all subdomains.

For applications where you're confident HTTPS is permanent, you can also add preload and submit your domain to browser preload lists — meaning browsers enforce HTTPS from the first visit, not just subsequent ones.

4. X-Content-Type-Options

This single-value header prevents browsers from MIME-sniffing — guessing the content type of a response based on content rather than the declared Content-Type header. Without it, a browser might execute an uploaded file as a script even if the server returns it as text/plain.

X-Content-Type-Options: nosniff

That's the entire header. One value. No configuration complexity. There is no good reason not to have this set.

5. Cookies: Secure and HttpOnly Flags

Session cookies without the Secure flag can be transmitted over unencrypted HTTP connections — which matters if the application is ever accessed over HTTP (even briefly, during a redirect) or if there's any mixed-content scenario. Setting the flag ensures the browser only sends the cookie over HTTPS.

The HttpOnly flag prevents JavaScript from accessing the cookie value. This is the primary mitigation for session hijacking via XSS — even if an attacker injects script into the page, they cannot read a HttpOnly session cookie.

Both should be set on all session and authentication cookies:

Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Strict

Adding SameSite=Strict (or at minimum Lax) also provides CSRF protection by restricting when cookies are sent on cross-site requests.

6. Suppress Server Version Headers

Not strictly a security header you add, but headers you remove. By default, many web servers disclose their software and version number in the HTTP response:

Server: Apache/2.4.57 (Ubuntu)
X-Powered-By: ASP.NET

This doesn't directly create a vulnerability, but it gives attackers a head start. Knowing you're running Apache 2.4.57 lets an attacker check immediately which CVEs apply to your version. Suppressing these headers removes a free intelligence advantage. In Apache, this is ServerTokens Prod and ServerSignature Off. In IIS, the X-Powered-By header can be removed in web.config.

How to Check Your Application Right Now

The quickest check is a single curl command:

curl -I https://yourdomain.com

This returns all response headers. Look for (or note the absence of) Content-Security-Policy, X-Frame-Options, Strict-Transport-Security, X-Content-Type-Options, and whether Server reveals a version number.

For a more thorough and scored check, securityheaders.com gives you an immediate report with grades and specific remediation advice. OWASP ZAP — which is free and open source — provides the same checks as part of a full automated web application scan, along with findings for CSRF, outdated libraries, and other common issues.

In a real assessment of a production SaaS application, four of these six issues were present simultaneously — CSRF tokens missing, no CSP, no clickjacking header, and an outdated jQuery library with multiple known CVEs. All of them were remediable with configuration changes and a library update.

These findings are not exotic. They appear in assessments of applications built by competent development teams who simply weren't focused on security headers. The fix is not complex. The reason to fix them is: each one represents a class of attack that is completely prevented by a header that takes minutes to add.