Joomla's core System - HTTP Headers plugin makes it easy to switch on several important security headers without touching server config files. But its coverage has real edges: two commonly requested headers are missing entirely, and one setting - the CSP nonce length - looks odd until you see the code behind it.
Since Joomla 4, the core System - HTTP Headers plugin has given site owners a way to configure security-relevant HTTP headers from the plugin manager instead of hand-editing .htaccess. It's a genuinely useful piece of core - but its scope is narrower than people expect, and two specific headers keep coming up in support threads: X-Content-Type-Options and Cross-Origin-Resource-Policy (CORP). Here's exactly what the plugin covers, what it doesn't, and why the CSP nonce is generated the way it is.
What the plugin actually configures
Looking at the plugin's manifest in Joomla 6.1.3, the "Plugin" tab has three dedicated controls:
- X-Frame-Options - a simple enable/disable switch (on by default).
- Referrer-Policy - a dropdown of the standard values, defaulting to
strict-origin-when-cross-origin. - Cross-Origin-Opener-Policy (COOP) - a dropdown defaulting to
same-origin.
Beyond that, there are two dedicated fieldsets: a full Strict-Transport-Security (HSTS) section (enable, max-age, subdomains, preload) and a genuinely detailed Content-Security-Policy (CSP) builder with 27 directive fields, report-only mode, script/style hash support, strict-dynamic, and nonce generation. If your site needs a real CSP, this builder is more capable than most people give it credit for.

The "Force HTTP Headers" field is a fixed list, not a blank box
The plugin also has a "Force HTTP Headers" subform, and it's tempting to assume it lets you add any header you like. It doesn't. Its header-name field is a closed dropdown (type="list", validate="options") with exactly eleven options: Content-Security-Policy, Content-Security-Policy-Report-Only, Cross-Origin-Opener-Policy, Expect-CT, Feature-Policy, NEL, Permissions-Policy, Referrer-Policy, Report-To, Strict-Transport-Security, and X-Frame-Options. There's no free-text option and no "custom" entry - so if the header you need isn't on that list, this subform can't help.
Why X-Content-Type-Options isn't there
X-Content-Type-Options: nosniff stops browsers from MIME-sniffing a response into a different content type than the server declared - a small but genuinely useful anti-sniffing header. It is not one of the plugin's options, on either the Plugin tab or the Force HTTP Headers list, in Joomla 6.1. This isn't something you're missing in the UI: it's a still-open core feature request asking for exactly this switch to be added.
Until it lands in core, set it at the server level. On Apache:
Header always set X-Content-Type-Options "nosniff"
On IIS, add the equivalent entry to web.config's customHeaders section. Either way, this is a one-line, low-risk addition worth making regardless of what the plugin covers.
Why CORP isn't there either (and how it differs from COOP)
Cross-Origin-Resource-Policy (CORP) is easy to confuse with Cross-Origin-Opener-Policy (COOP), which the plugin does support. They solve different problems: CORP tells browsers whether a specific resource (an image, a script) can be loaded cross-origin, while COOP controls whether your page shares a browsing context group with cross-origin windows it opens. Joomla's core plugin only ships COOP - CORP isn't in the manifest at all, so if you need it (for example, to lock down direct hotlinking of media assets), it has to go through your web server config or a small custom system plugin, the same way as X-Content-Type-Options above.
The CSP nonce: why 64, not 16?
If you enable nonces under the CSP tab, Joomla generates one automatically per request. Reading the actual plugin code, the nonce comes from random_bytes(64) - 64 raw random bytes (512 bits) of entropy, then hex- and base64-encoded before it's used in the nonce- source and injected into your inline <script>/<style> tags. The commonly cited minimum for a CSP nonce is 128 bits (16 bytes) of entropy - enough to make guessing infeasible. Joomla's 64 bytes is far more generous than that floor, not a mistake: more entropy costs essentially nothing per request and gives extra headroom. There's no setting to change the length, and there's no real reason you'd want to.

A practical hardening order
If you're setting this plugin up from scratch, a sane order is: enable X-Frame-Options, set a Referrer-Policy, turn on COOP, build your CSP starting in report-only mode so you can see what it would have blocked before you enforce it, add HSTS once your HTTPS setup is solid, and then layer X-Content-Type-Options and CORP in at the server level to close the two gaps core doesn't cover yet. This is one piece of a bigger picture - see how gaps like these get exploited in practice in how a secure Joomla site got hacked anyway, and our guide on how hacked Joomla sites stay hacked for the broader hardening picture these headers are part of.
None of this is exotic - it's mostly filling in headers most sites simply never set. The core plugin gets you most of the way there in a few clicks; the rest is a couple of lines in your server config.
Not sure your site's security headers are set up right?
Headers are one small part of hardening a Joomla site properly. If you'd rather have someone check the whole picture - headers, extensions, permissions, and the gaps attackers actually use - I review and harden Joomla installs end to end.
