X-Content-Type-Options

X-Content-Type-Options stops browsers guessing a file's type from its content, closing a route attackers use to smuggle scripts past file uploads.
How common is this?
- 32.4% of the Joomla sites we have this data for fail this check. Platform: Joomla.
Measured across the sites we audit, on each site's most recent snapshot.
What this check and mySites.guru tool looks at on your site
mySites.guru requests a page from your Joomla extension site and reads back the HTTP response headers to check whether X-Content-Type-Options is present and set to nosniff, its only valid value. We check this against a page your server answers directly, such as a 404, rather than only the homepage, so the result reflects the whole site rather than just whatever a Joomla extension can add to a PHP response. It’s one of the header checks walked through in checking your website’s security headers with mySites.guru.
How a browser’s guesswork turns into script execution
Every response your server sends carries a Content-Type header declaring what kind of file it is: text/html, image/jpeg, application/javascript, and so on. Browsers are supposed to trust that declaration, but historically they didn’t always. Older versions of Internet Explorer and Chrome would look past the declared type and inspect the actual bytes of a file to guess what it “really” was, a behaviour called MIME sniffing, and would sometimes act on that guess instead of the header.
That becomes a real problem the moment a site accepts any kind of upload. Imagine a file uploaded with an image extension and an image/jpeg Content-Type, but whose actual content is a script. A browser that trusts the declared type renders it as a broken image and moves on. A browser that sniffs the content can decide it’s actually HTML or JavaScript and execute it, which is exactly the kind of gap that turns an innocuous file upload feature into a cross-site scripting vector. nosniff closes that gap by telling the browser, unambiguously, to stop guessing and use the declared type.
There’s a second, related risk worth knowing about even though nosniff doesn’t fully solve it on its own: reflected file download attacks, where an attacker crafts a URL that returns attacker-controlled content with a filename and content type engineered to make the browser offer it as a download, disguised as something trustworthy, like a PDF invoice that’s actually a batch script. nosniff narrows the gap by stopping the browser reinterpreting the content type on its own initiative, though the server still needs to set a correct Content-Type and, ideally, a Content-Disposition header in the first place for downloads it serves deliberately.
One value, and nothing weighed against it
There’s only one value worth sending, and only one decision to make:
X-Content-Type-Options: nosniff
There’s no trade-off to weigh here the way there is with Content-Security-Policy or HSTS. nosniff has no legitimate downside for any normal site, costs nothing to add, and every response should carry it. Since Joomla 3.9.3, this header has shipped in Joomla’s own distributed .htaccess and web.config files, so a site that’s never had its server config touched since installing usually already has it. It’s the sites where that default .htaccess has been replaced or heavily customised where this check tends to fail.
In practice, that’s a more common situation than it sounds. A site moved between hosts, a caching plugin that rewrites .htaccess as part of its own setup, a hosting control panel that regenerates the file from its own template, or simply a developer who replaced the whole file years ago and never thought to check what Joomla’s original version contained, can all quietly drop this header along with whatever else Joomla shipped by default. None of those situations look like a mistake from the inside. The site works, nothing throws an error, and the missing header sits unnoticed until something checks for it specifically.
How to fix it
Set the header at server level so every response carries it, static files included, not just the ones Joomla itself renders. In an .htaccess file, for https://yoursite.com/administrator and your front end alike:
Header always set X-Content-Type-Options "nosniff"
On nginx, inside your server block:
add_header X-Content-Type-Options "nosniff" always;
- Check your current
.htaccess(or nginx config) for an existingX-Content-Type-Optionsline. If your server config has been rebuilt or replaced since installing Joomla, it may have been dropped along with the rest of Joomla’s shipped defaults. - Add the directive above at server or virtual host level.
- Confirm it’s present with a quick header check:
curl -sI https://yoursite.com/and look forx-content-type-options: nosniffin the response. - Check a non-PHP path too, such as an image or CSS file directly, not just the homepage. A header added through a Joomla extension only appears on responses PHP actually handles, so a server-level fix should show up everywhere while a plugin-only one won’t.
- There’s no follow-up testing needed beyond that. Unlike Content-Security-Policy or Strict-Transport-Security, this header has no failure mode that breaks legitimate functionality, so once it’s confirmed present, the job is done.
What mySites.guru does about it
Setting this header means editing server or virtual host config, which sits outside what a Joomla extension can reach, so we don’t apply it for you. mySites.guru checks for X-Content-Type-Options: nosniff on every snapshot, twice a day, and flags it clearly when it’s missing, alongside the other response headers we check: Content-Security-Policy, Strict-Transport-Security and X-Frame-Options.
X-Content-Type-Options
mySites.guru checks every connected site for this automatically and flags it the moment it appears. These run twice a day on every connected site.
Further Reading
- Scott Helme: hardening your HTTP response headers (X-Content-Type-Options)
- KeyCDN: What is X-Content-Type-Options?
- KeyCDN: What is MIME sniffing?
KeyCDN's support articles go into more depth on MIME sniffing than we have room for here.