Guide

Security headers and CORS, in plain words

Checked on 1 November 2026

Short answer

Security headers are short settings your server sends with every page to tell the browser to block common tricks against your visitors, and a small app needs five: Content-Security-Policy, frame-ancestors or X-Frame-Options, Strict-Transport-Security, X-Content-Type-Options and Referrer-Policy.

Check your site for free with Mozilla’s HTTP Observatory or your browser’s developer tools, then add the missing headers in your host’s settings or your app’s server code. Make sure CORS, the setting that says which other websites may read your app’s answers, never lets every website read your app with your users’ cookies. Most of these fixes are quick, but a database table that strangers can read is more urgent.

LidTight’s free check looks for four of these headers and tests CORS. On Tidybook, our demo app built with Lovable, it rated two missing headers as medium on 1 November 2026, and an open table in the same app as critical.

1.What a security header is

When a browser opens your app, the server sends the page plus a few lines of extra information, such as “X-Frame-Options: DENY”. These lines are HTTP headers. Visitors never see them, but the browser reads every one.

A security header asks the browser to be stricter: run no scripts from unknown places, do not show this page inside another site, always use an encrypted connection. Without it, the browser uses a looser default, and nothing visibly breaks. Security headers protect your visitors in their browser. They do not protect your database.

2.The five headers that matter for a small app

MDN, Mozilla’s reference for web developers, rates each of these fixes for impact and difficulty.

HeaderWhat it blocksMDN’s rating
Content-Security-Policy (CSP)Scripts from places you did not list. If an attacker slips code into your page (cross-site scripting, or XSS), the browser refuses to run it.High impact, high difficulty
frame-ancestors (part of CSP) or X-Frame-OptionsOther sites showing your page inside a hidden frame to trick a signed-in user into clicking your buttons (clickjacking).High impact, low difficulty
Strict-Transport-Security (HSTS)Unencrypted visits. The browser remembers to use HTTPS for your domain and does not let users click past a certificate error.High impact, low difficulty
X-Content-Type-Options: nosniffThe browser guessing a file’s type, so a file you serve as plain text cannot run as a page or a script.Low impact, low difficulty
Referrer-PolicyFull page addresses leaking to other sites, with any private paths or codes in them.Low impact, low difficulty

Content-Security-Policy

CSP is the strongest of the five and the hardest to get right: a strict policy can block your own fonts, analytics or database calls until you list them. MDN advises testing a policy first with the Content-Security-Policy-Report-Only header, which reports problems instead of blocking. A CSP is a second layer of defense. It does not replace cleaning what users type. Each part of a CSP works on its own, so you can start with framing protection alone.

Framing protection

In clickjacking, another site loads your page in an invisible frame and puts its own button in the same place as one of yours, so the user’s click lands in your app, signed in as them. Without a header, the browser lets any site embed your page. MDN advises setting both frame-ancestors and X-Frame-Options, as real headers: frame-ancestors is not supported in a meta tag, and X-Frame-Options in a meta tag has no effect.

HSTS, nosniff and Referrer-Policy

HSTS makes the browser switch every visit to your domain to HTTPS, for as many seconds as its max-age says. Send it only when your whole site works on HTTPS.

X-Content-Type-Options has one value, nosniff, and MDN says all sites should send it. It matters most when users upload files: it stops an uploaded text file from running as a web page. See Can anyone upload files to your app at your cost?

Referrer-Policy decides how much of your page address other sites learn. Today’s default, strict-origin-when-cross-origin, tells them only your domain. The default was looser before, so set it yourself.

3.What CORS is, and the one mistake to avoid

Under the same-origin policy, a page from one origin (the protocol, domain and port, such as https://yourapp.com) cannot read answers from another. This stops a bad website from reading a user’s webmail while they are signed in.

CORS (Cross-Origin Resource Sharing) is how your server makes exceptions. The Access-Control-Allow-Origin header names the sites whose pages may read the answer. Access-Control-Allow-Credentials: true lets those pages read answers to requests that carry the user’s cookies.

The mistake: every site, with cookies

The value * (any site) does not work with cookies: the browser blocks the answer. One way around this is to copy back whatever origin the request names, and allow cookies. Then a page on any website can read what your app shows a signed-in user. MDN warns against exactly this. Its fix:

  • If other sites must read your app with cookies, check the request’s origin against a fixed list and name only that site in the answer, with Vary: Origin, which tells caches that the answer depends on the asking site.
  • If your data is public and needs no cookies, * is fine, without Access-Control-Allow-Credentials.
  • Otherwise, send neither header.
Access-Control-Allow-Origin: https://www.yourapp.com
Access-Control-Allow-Credentials: true
Vary: Origin

CORS is a browser rule, not a lock on your data. MDN describes CORS as the system that decides whether browsers block a page’s code from reading another site’s answers. A stranger does not need a browser. Our free check is a program on a server, and it found Tidybook’s reviews table open to anyone (below). Your database rules protect your data. See My Supabase public key is visible. Is that a problem?

4.How serious a missing header is

On 1 November 2026, LidTight’s free check ran on Tidybook, our demo app built with Lovable. It reported this finding as medium: “Some browser protections are switched off · Missing: content security policy, protection against framing”. Its note says these settings “are quick to turn on.”

The same run rated Tidybook’s reviews table critical: 12 rows with first names, emails and phone numbers, readable without signing in. An open table gives your customers’ data to anyone, today. A missing header leaves visitors open to tricks such as clickjacking, or removes a second layer against injected scripts. Fix your tables first (see What can a stranger see in your app?), then add the headers.

What the free check covers: it looks for HSTS, CSP, nosniff and framing protection on the page at the link you enter. It checks that each header is there, not how strict it is, and it skips Referrer-Policy. For CORS, it asks your page, and the read-only endpoints it finds in your code, as if from another website. It reports an app that copies that site back and allows cookies: high when the app signs in with cookies, low when it does not. The Tidybook run reported no CORS finding.

5.How to check your own site for free

  1. Open MDN HTTP Observatory, Mozilla’s free header checker, enter your app’s domain and click Scan. It gives a grade and a fix for each problem, with a link to MDN’s guide for it.
  2. Open your app in your browser and open the developer tools: Ctrl + Shift + I or F12 on Windows, ⌘ + ⌥ + I on a Mac.
  3. Click the Network tab and reload the page. The tools record requests only while they are open.
  4. Click the request for your page’s address, open the Headers tab and read Response Headers. Look for the five names above.
  5. If your app shows a CORS error, open the Console tab. MDN says only the console shows what went wrong.
  6. Run our free check to see the headers next to what matters more: open tables, secret keys in your code and files that should not be public.

Anyone can scan any domain with Observatory, and each domain’s scan history is public, its FAQ says. The same FAQ says an A+ grade does not mean a site is secure: Observatory does not test for things like outdated software or SQL injection.

6.How to set headers on your host

These are the hosts whose official docs we checked on 1 November 2026.

HostWhere to set headersWatch out
NetlifyA file named _headers in your publish folder, or a headers section in netlify.tomlNot applied to pages made by functions, such as server-rendered pages. Those must send their own headers.
Cloudflare PagesA file named _headers in your static files folder, often public/Not applied to responses from Pages Functions or server-rendered frameworks. Set the headers in that code.
VercelA headers list in vercel.jsonApplies to static files and functions, matched by path.

A starting _headers file for Netlify or Cloudflare Pages:

/*
  Content-Security-Policy: frame-ancestors 'none'
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Strict-Transport-Security: max-age=63072000

Its CSP line only controls who may frame your page, so it cannot block your scripts. Grow the policy later, with Report-Only first. To show your app inside another site of yours, list that site in frame-ancestors. The max-age value, two years, is the one MDN recommends.

Lovable hosting. We found no custom header setting in Lovable’s hosting, publishing and security docs. Lovable apps created from 13 May 2026 use server-side rendering, so if you move one to Netlify or Cloudflare Pages, set its headers in code, not only in _headers.

If you cannot set headers at all, a CSP can go in a meta tag. Framing protection cannot, so ask your host for it. For the rest of your launch checks, see Before you go live: a security checklist.

Sources

  1. MDN: HTTP headersdeveloper.mozilla.org
  2. MDN: Practical security implementation guidesdeveloper.mozilla.org
  3. MDN: Content Security Policy (CSP) guidedeveloper.mozilla.org
  4. MDN: Content Security Policy (CSP) implementationdeveloper.mozilla.org
  5. MDN: Clickjackingdeveloper.mozilla.org
  6. MDN: X-Frame-Options headerdeveloper.mozilla.org
  7. MDN: CSP frame-ancestors directivedeveloper.mozilla.org
  8. MDN: Strict-Transport-Security headerdeveloper.mozilla.org
  9. MDN: X-Content-Type-Options headerdeveloper.mozilla.org
  10. MDN: MIME type verificationdeveloper.mozilla.org
  11. MDN: Referrer-Policy headerdeveloper.mozilla.org
  12. MDN: Same-origin policydeveloper.mozilla.org
  13. MDN: Cross-Origin Resource Sharing (CORS)developer.mozilla.org
  14. MDN: Cross-Origin Resource Sharing (CORS) configurationdeveloper.mozilla.org
  15. MDN glossary: CORSdeveloper.mozilla.org
  16. MDN HTTP Observatorydeveloper.mozilla.org
  17. MDN HTTP Observatory: FAQdeveloper.mozilla.org
  18. MDN: Transport Layer Security (TLS) configurationdeveloper.mozilla.org
  19. MDN: What are browser developer tools?developer.mozilla.org
  20. Chrome DevTools: Network features referencedeveloper.chrome.com
  21. Netlify: Custom headersdocs.netlify.com
  22. Cloudflare Pages: Headersdevelopers.cloudflare.com
  23. Vercel: Static configuration with vercel.jsonvercel.com
  24. Lovable: How Lovable hosts your appdocs.lovable.dev
  25. Lovable: Deploying and hosting outside Lovabledocs.lovable.dev