PL-032lowLive posture

No X-Content-Type-Options: nosniff

Browsers may guess a file’s type from its contents, so an uploaded “image” can be run as a script or page.

Severity
Low
Who can exploit it
Anyone who can get a file served from your domain
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

Every response says what it is with Content-Type. Without X-Content-Type-Options: nosniff, browsers may second-guess that label by looking at the bytes (“MIME sniffing”). PL-032 means your page doesn’t send nosniff.

The risk is files you didn’t write. If users can upload files that your domain serves back, a file labelled as plain text or an image but containing HTML or JavaScript can be treated as a page or a script. With nosniff, the browser trusts the label and refuses to run a script whose type isn’t a script type.

Why AI builders produce it

It is a header with nothing to configure, so it gets skipped along with the rest of the hosting setup. Modern hosts send correct content types for your own files, which hides the gap until user uploads arrive.

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 x-content-type-options line

Check it yourself

check-pl-032.sh
curl -sI https://your-app.com | grep -i x-content-type-options
# good: x-content-type-options: nosniff

# check your JavaScript bundle too: its type must be a script type
curl -sI https://your-app.com/assets/index.js | grep -i content-type

The fix

the header
X-Content-Type-Options: nosniff

It has one valid value and almost never breaks anything. The one thing to confirm afterwards: scripts and styles must be served with the right type (text/javascript, text/css), which every major host already does for built assets.

Vercel

vercel.json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        { "key": "X-Content-Type-Options", "value": "nosniff" }
      ]
    }
  ]
}

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)
/*
  X-Content-Type-Options: nosniff

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

For a site proxied through Cloudflare (orange cloud), add a Response Header Transform Rule (Rules → Transform Rules in the dashboard): match all incoming requests to your hostname, then Set static header X-Content-Type-Options to:

X-Content-Type-Options · value
nosniff

On Cloudflare Pages or Workers static assets, a _headers file in your build output works the same way 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.

nosniff only works as a response header, not as a meta tag.

Uploaded files are better still served from a different domain. Supabase Storage already does that: files come from your supabase.co project host, not your app’s domain. Keep personal uploads in a private bucket (PL-007).

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
          x-content-type-options
          not sent                       FLAG
synthetic exampleLive posture · read from the home page’s response

Live posture reads the header from the final response of its one page load and passes it only when the value is nosniff. It sees the home page, not your other files, so set the header for every path (the snippets above do).

When the pattern is intended

There is no common reason to leave it out. Set it everywhere.

Why it’s rated low

Low: it only becomes exploitable when someone can get a file served from your domain. It is the cheapest fix on this list. 5 points in the Live posture grade.

Guides

Free check

Does your site have PL-032?

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.