Skip to content

Test your website now

Free, no card. We read only public pages.

Run free audit →

Security · Medium severity

X-Content-Type-Options Header Missing: Add Nosniff Safely

Fix a missing X-Content-Type-Options header. Add nosniff, correct script and stylesheet MIME types, verify downloads, and test error and asset responses.

Published · Updated

What the check tests

Check
sec.headers.nosniff - X-Content-Type-Options: nosniff
Passes when
Serve X-Content-Type-Options: nosniff on all responses.
Scope
graded on every page crawled
Severity
Medium
Fix effort
small - under an hour
Impact when fixed
medium

In one paragraph

A missing X-Content-Type-Options header leaves the response without an explicit nosniff instruction. That matters especially when browsers load scripts or stylesheets with incorrect MIME types. Send X-Content-Type-Options: nosniff and configure accurate Content-Type values at the same time. Verify assets, downloads, and error responses, not just HTML pages; the header is not a replacement for safe upload handling.

Why it matters

MIME types describe what a response contains. A server normally declares one through Content-Type, such as text/css for a stylesheet or an appropriate JavaScript MIME type for a script. Browser sniffing can otherwise infer a different interpretation in some contexts.

The most important nosniff enforcement rules concern script and style destinations. A browser blocks a script with an unacceptable script MIME type and a stylesheet not served as text/css. The effect is context-specific; nosniff is not a universal content validator that examines every file and rejects anything whose bytes disagree with an extension.

This is defence in depth, not a complete upload security design. If an attacker-controlled document is intentionally served as text/html, nosniff does not make that correctly labelled HTML harmless. Use appropriate validation, authorisation, content disposition, and origin separation for untrusted files.

How WebAuditOS evaluates this finding

The supplied check reads response headers on every fetched response, not only HTML. X-Content-Type-Options with the expected nosniff value passes; a missing header or another value fails. A request with no response is not graded.

That verifies a declared control, not resource correctness. A response with nosniff and a broken MIME type can pass the header check while its stylesheet or script fails in the browser. Conversely, a missing header does not demonstrate that a particular exploitable sniffing path exists. Inspect the actual response and browser context.

How to fix it

  1. Find the layer serving the failing URL. Application middleware may cover HTML while a CDN, object store, or dedicated static server handles assets and uploads without the same header. Check the exact URL in the evidence.
  2. Add the single defined value:
X-Content-Type-Options: nosniff

For nginx, an illustrative configuration is:

add_header X-Content-Type-Options nosniff always;

For Apache with the headers module:

Header always set X-Content-Type-Options nosniff

Integrate the directive with your existing header configuration. Check route overrides, server-version-specific inheritance, and whether a CDN modifies the final response. The always option helps cover error statuses as well as ordinary responses.

  1. Fix Content-Type mappings rather than relying on sniffing. Check production JavaScript and CSS, generated assets, uploaded documents, API responses, and custom error pages. A JavaScript URL returning an HTML fallback is a routing problem as well as a type problem; relabelling that error document as JavaScript is not a valid fix.
  2. Check object-storage metadata and CDN caches. A corrected origin mapping may not immediately replace a cached response with the old type. Purge or version affected assets according to your deployment process.
  3. Test realistic browser loading. Open DevTools and inspect the Console and Network panel while exercising navigation and interactive features. Confirm that scripts execute, styles apply, and failed asset requests are not silently replaced by a successful HTML page.
  4. Test uploads and downloads separately. Use Content-Disposition: attachment where the file is intended to download, and consider a separate origin for user-controlled content. Do not assume a blanket header makes active document formats safe to render on your application origin.
  5. Verify representative success and error responses externally, then rescan. For example:
curl -I https://example.com/assets/app.js

Check both Content-Type and X-Content-Type-Options. If HEAD differs from GET in your stack, repeat with a normal GET before concluding that browser behaviour is covered.

What the fix can break

The common rollout failure is a script or stylesheet that previously depended on incorrect labelling. The browser may now refuse it, leaving a broken interface despite successful HTTP responses. Correct the MIME type or routing rather than removing nosniff globally.

Changes to download behaviour can depend on the declared type, Content-Disposition, browser, and navigation context. Test supported document workflows instead of promising that every generic download will render or stop rendering identically.

Duplicate headers from several layers can also make deployment confusing. Configure a clear owner and inspect the final public response. Do not rely on a duplicate-header interpretation as a substitute for emitting one intentional, valid value.

Questions

Does nosniff validate the actual contents of uploads?

No. It is a browser response-handling control, not malware scanning, format validation, or access control. Design those protections separately.

Why did a stylesheet stop working after adding nosniff?

Inspect its Content-Type and body. A stylesheet must be served as text/css; an HTML error page at the CSS URL is not a usable stylesheet regardless of the status code.

Should I add the header only to HTML?

No. Script, stylesheet, upload, and download responses also matter, and the supplied check can inspect non-HTML responses reached by the crawl.

Review Content-Security-Policy, framing protection, and the security headers guide. Each adds a different browser control.

Standards and sources

  • OWASP Secure Headers

In the report

Test this on your own site

Every scan runs sec.headers.nosniff on every page it crawls, on every plan. The finding carries this id, so a line in a report can be matched to the explanation above - and the free scan needs no account.