Security

Security headers in Joomla: the plugin you already have

Security headers in Joomla: the plugin you already have

Joomla ships a System - HTTP Headers plugin for X-Frame-Options, Referrer-Policy, HSTS and CSP. What each setting does and how to test your headers.

Every page your site sends comes with a set of HTTP headers that visitors never see. A few of them tell the browser how strict to be: whether the page may be shown inside someone else's frame, whether it may ever be loaded over plain HTTP again, and which scripts it is allowed to run. Joomla has been able to set these since version 4, through a plugin most site owners have never opened.

Where the settings live

Go to System > Plugins and search for HTTP Headers. The plugin is called System - HTTP Headers and on a fresh Joomla 4, 5 or 6 install it is already enabled. Sites that were upgraded from Joomla 3 sometimes have it disabled, so check that first. If it is off, none of what follows is being sent.

The plugin sets headers from PHP, so it works the same on Apache, nginx and LiteSpeed. The flip side: it only applies to pages Joomla generates. Images, CSS and JavaScript files are served straight by the web server and do not get these headers. For most of them that does not matter.

The four switches on the first tab

  • X-Frame-Options. When on, Joomla sends SAMEORIGIN: your pages can be framed by your own site but not by others. This stops clickjacking, where an attacker loads your login form invisibly inside their page. Leave it on unless another site legitimately embeds yours in an iframe, such as a partner portal or a booking widget.
  • Referrer-Policy. Controls how much of the current URL is passed on when a visitor clicks a link to another site. The default, strict-origin-when-cross-origin, sends only your domain name to other sites and never leaks over HTTP. That is a good default; there is rarely a reason to change it.
  • Cross-Origin-Opener-Policy. With same-origin, a page opened from your site in a new window cannot reach back into your page through window.opener. It can break payment or login pop-ups that rely on talking back to the page that opened them. If a PayPal or social login pop-up stops closing after checkout, try same-origin-allow-popups.
  • Strict-Transport-Security (HSTS). Tells the browser to use HTTPS for your domain for a set period, even if someone types http:// or follows an old link. This one needs care, see below.

HSTS: turn it on, but in steps

Once a browser has seen an HSTS header, it refuses to load your site over HTTP until the max-age runs out. The default in Joomla is 31536000 seconds, one year. If your certificate expires or you move to a host without HTTPS, returning visitors get a hard error with no button to continue.

A safe order:

  1. Make sure HTTPS works everywhere first. In System > Global Configuration > Server, set Force HTTPS to Entire Site and browse around for mixed-content warnings.
  2. Switch HSTS on with a short max-age, for example 300 (five minutes). Check the site in a few browsers.
  3. Raise it to a week, then to a year.
  4. Only switch on Subdomains if every subdomain has a working certificate, including the old webmail. or test. ones nobody remembers.
  5. Leave Preload off unless you plan to submit the domain to the browser preload list. Getting off that list takes months.

Content Security Policy

The second tab handles Content Security Policy, the header that tells the browser which sources of scripts, styles, images and frames are allowed. A tight CSP is the strongest protection against injected JavaScript, and also the setting most likely to break your site. Every extension that loads Google Fonts, an analytics script, a map or a YouTube embed needs its source listed.

Do not start in enforcing mode. Switch on CSP in report only mode, add the directives you think you need, and open the site with the browser console open. Every blocked resource shows up as a warning while nothing actually breaks. Add sources until the warnings stop, then switch report only off. Joomla can also add a nonce to its own inline scripts, which saves you from allowing 'unsafe-inline' for core output. Third-party extensions that print inline script without that nonce will still be blocked, so test their pages too.

If you have a large site with many extensions and no time to test, skip CSP for now. The other headers give you most of the benefit with almost no risk.

Watch for double headers

Many hosts already send some of these headers from the server configuration or a control panel, and some security extensions add them too. If the same header arrives twice with different values, browsers may pick the strictest, the first, or ignore both. Check what actually goes out:

curl -sI https://www.example.com/ | grep -iE 'strict|frame|referrer|opener|content-security'

Each header should appear once. If one shows up twice, remove it either from the plugin or from the server, not both. Online scanners such as securityheaders.com give the same information with a grade, which is handy for showing a client the before and after.

Headers protect visitors' browsers. They do nothing for a stolen admin password, so pair them with two-factor login for administrators.

Stuck on something else?

Doctor Joomla is a project of Cloudfaction, a Dutch agency building and maintaining Joomla sites since 1999. The articles are made with the help of AI, so tell us if something does not match your screen. Mail info@cloudfaction.nl if you want someone to look at yours.

Rather have someone look at it

Doctor Joomla is a Cloudfaction project.

A Dutch agency that has been building and running Joomla sites since 1999. If your site needs more than an article can fix, get in touch.