akash@portfolio ~
› establishing secure channel...
AB
Akash Bishnoi
All Writeups
AppSec·May 18, 2026· 2 min read

Hardening HTTP Security Headers: From F to A+

Web SecurityOWASPHeadersNext.js

Most web apps ship with a response that quietly leaks attack surface. No Content-Security-Policy, a chatty Server header, framing wide open. None of it shows up in a demo, so it survives to production. This is the exact checklist I run to take a site from an F to an A+ — and why each header earns its place.

Try it live: the Security Toolkit on this site scans any URL and grades its headers the same way.

The headers that matter

Content-Security-Policy

The single strongest defense against XSS. It tells the browser which sources are allowed to load scripts, styles, images, and more. Start in report-only mode so you don't break the app while you tune it:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'

Once the violation reports are clean, drop -Report-Only and enforce. Avoid unsafe-inline on script-src — it's the loophole that makes most CSPs decorative.

Strict-Transport-Security

Forces HTTPS for a set duration and blocks protocol-downgrade attacks. Once you're confident in your certs:

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

The supporting cast

  • X-Frame-Options: DENY — kills clickjacking by refusing to be framed.
  • X-Content-Type-Options: nosniff — stops MIME sniffing that can turn an upload into a script.
  • Referrer-Policy: strict-origin-when-cross-origin — stops full URLs (with tokens) leaking to third parties.
  • Permissions-Policy — disables powerful APIs you don't use: geolocation=(), camera=(), microphone=().

Applying it in Next.js

Set them once in next.config.mjs and every route inherits them:

const securityHeaders = [
  { key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains; preload" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-Frame-Options", value: "DENY" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" }
];

export default {
  async headers() {
    return [{ source: "/:path*", headers: securityHeaders }];
  }
};

The mindset

Security headers are cheap insurance: a few lines of config that shrink your attack surface before an attacker ever probes it. Scan your own site, fix the reds, and re-scan. Defense should be measurable — a letter grade you can point to, not a vibe.

Have a security or AI project?

I build secure, intelligent systems end-to-end. Let's talk about yours.

Get in touch