PL-029lowLive posture

No HSTS header, or max-age under 180 days

Browsers aren’t told to use HTTPS only, so a visitor’s first request can still go out over plain HTTP.

Severity
Low
Who can exploit it
Someone on the visitor’s network, before the redirect happens
Found by
PatchLabs Live posture: your home page’s response headers
Lab proof
Not lab-proven: read from your home page’s response

What it is

HSTS (HTTP Strict Transport Security) is one response header: Strict-Transport-Security: max-age=63072000. Once a browser has seen it over HTTPS, it refuses to use plain HTTP for your domain for that many seconds, and won’t let the visitor click past a certificate warning. PL-029 means the header is missing, or its max-age is below 180 days (15,552,000 seconds), too short to cover people who visit now and then.

Without it, a redirect from http:// (PL-027) still leaves one unprotected request every time someone types your domain or follows an old http:// link. That single request is where an attacker on the network can stop the upgrade and keep the visitor on HTTP.

Why AI builders produce it

HSTS lives in hosting config, which app generators rarely write. Some platforms add it to their own subdomains but not to custom domains, so the header disappears exactly when the app gets its real name.

What we see

A synthetic example for app.example.com, shortened. Not taken from any real site.

curl -sI https://app.example.com (response, shortened)
$ curl -sI https://app.example.com
HTTP/2 200
content-type: text/html; charset=utf-8
# no strict-transport-security line

Check it yourself

check-pl-029.sh
curl -sI https://your-app.com | grep -i strict-transport-security
# good: strict-transport-security: max-age=63072000; includeSubDomains
# 180 days = 15552000 seconds; anything lower is reported

The fix

Send this on every HTTPS response. Two years is the usual value. Add includeSubDomains only when every subdomain serves HTTPS, and preload only if you intend to submit the domain to the browsers’ preload list, which is hard to undo.

the header
Strict-Transport-Security: max-age=63072000; includeSubDomains

Vercel

vercel.json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains" }
      ]
    }
  ]
}

Put vercel.json at the root of the project and redeploy. If the file already has a headers array, add the object to it rather than starting a second one.

Netlify

public/_headers
# public/_headers  (Vite copies public/ into the publish folder)
/*
  Strict-Transport-Security: max-age=63072000; includeSubDomains

The file must end up in your publish directory (dist for Vite). Bolt projects deployed to Netlify use this file too. The same rule can live in netlify.toml under [[headers]] if you prefer one config file.

Cloudflare

Cloudflare has a switch for this: SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS). Set max-age to 12 months or more, and tick “Include subdomains” only if they all serve HTTPS. On Cloudflare Pages without a proxied zone, use a _headers file as on Netlify.

Lovable

Lovable’s documentation (checked 10 Nov 2026) doesn’t describe a way to set your own response headers on Lovable hosting. It does let you connect a custom domain through Cloudflare: choose “Uses Cloudflare or similar proxy” when you add the domain. Cloudflare can then add the header for you, as in the Cloudflare tab. If that changes, the header and value above are the same wherever you set them.

HSTS has to be a real response header: it can’t be set with a <meta> tag.

Make sure HTTPS works on every hostname first (PL-028): once browsers have cached HSTS, a broken certificate becomes a hard error with no way past it.

Live posture findings come with the header or setting to change. PatchLabs never changes your hosting or your repo.

How PatchLabs finds it

live posture · report excerpt
[LOAD]    https://app.example.com/ → 200
          strict-transport-security
          not sent                       FLAG
synthetic exampleLive posture · read from the home page’s response

Live posture reads the Strict-Transport-Security header from the final response of its one https:// page load, after at most 5 redirects, and compares max-age with 180 days. Sites on a top-level domain that is itself on the browsers’ HSTS preload list, such as .app or .dev, pass without the header, since browsers already use HTTPS only for them. It doesn’t look up whether your own domain was submitted to the preload list.

When the pattern is intended

Briefly, while you roll it out: start with a small max-age such as 300, confirm nothing breaks, then raise it. A short value is reported until you do, which is the point.

Why it’s rated low

Low: it matters only on the first or plain-HTTP request, and only to someone positioned on the network. It is a cheap, one-line fix, so it still counts: 5 points in the Live posture grade.

Guides

Free check

Does your site have PL-029?

Type your site’s address. The free headers check loads your public home page once, like any visitor, and grades HTTPS, the certificate, security headers, cookie flags and mixed content. No sign-up, and the result isn’t stored.

Free, no sign-upLoads your public home page onlyHow Live posture works

Last reviewed 10 Nov 2026. Finding IDs are stable: link to them freely. Spotted a mistake? Tell us.