Signs missing at the front door
Watch it happen
The bank has no signs. Mallory frames the bank’s window behind a fake prize booth, and Alice unknowingly presses the bank’s Approve button.
Alice walks up to a bank that has put up no signs at the door about who may show its windows.
In bank terms and app terms
| In the bank | In your app |
|---|---|
X-Frame-Options: DENY or CSP frame-ancestors | |
Strict-Transport-Security (HSTS) forces HTTPS | |
Content-Security-Policy limits where scripts can load from | |
Are you exposed?
Your site is a Next.js, Express or Vite app and you have never configured response headers. Running a header checker on your live URL shows missing Content-Security-Policy, Strict-Transport-Security or X-Frame-Options. Your server answers with X-Powered-By: Expressor aServerheader that shows an exact version.
Add the headers once for every route: headers()in next.config.js,helmet()in Express, or your host’s headers file.Start with Strict-Transport-Security,X-Content-Type-Options: nosniff,X-Frame-Options: DENY(or CSPframe-ancestors 'none') and aReferrer-Policy.Add a Content-Security-Policy such as default-src 'self', then loosen only what your app really needs. RemoveX-Powered-By.
What it looks like in code
// next.config.js
const securityHeaders = [
{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains" },
{ key: "Content-Security-Policy", value: "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" }, // add a nonce-based script-src if you need inline scripts
{ 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=()" },
]
module.exports = {
async headers() {
return [{ source: "/(.*)", headers: securityHeaders }]
}
}
Ask your AI tool to fix it
Paste this into Cursor, Claude, Lovable, Bolt or whatever you build with.
Add security headers to every response in this app. Set Strict-Transport-Security (max-age=63072000, and includeSubDomains only if every subdomain already serves HTTPS), X-Content-Type-Options: nosniff, X-Frame-Options: DENY (or CSP frame-ancestors), Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy that disables camera, microphone and geolocation, and a Content-Security-Policy that starts from default-src 'self'. Remove X-Powered-By and any version in the Server header. Then check that the site still works and tell me what I had to allow in the CSP.Where this comes from
The facts, figures and fixes on this page were checked against these sources on 25 Oct 2026. They are linked so you can check for yourself.
- Strict-Transport-Security headerMDN Web DocsHSTS forces HTTPS; max-age 63072000; includeSubDomains covers all subdomains
- X-Frame-Options headerMDN Web DocsDENY blocks framing and clickjacking; CSP frame-ancestors is the newer option
- Content Security Policy (CSP)MDN Web DocsCSP limits where scripts load from; default-src 'self' as a starting policy
- HTTP Headers Cheat SheetOWASPRecommended values for nosniff, Referrer-Policy, Permissions-Policy; remove X-Powered-By/Server
- headers (next.config.js)Next.jsSetting security headers for all routes with headers() in next.config.js
- Production best practices: SecurityExpresshelmet() sets security headers and removes X-Powered-By
Spot a mistake or something out of date? Report a correction · How these guides are made and checked
The free, open-source scanner checks for most of the problems in these guides.