/ Security Audit Fixes / Joomla

How to Fix Security Headers in Joomla

Joomla 4 and 5 ship with a built-in HSTS toggle in Global Configuration but rely on the server (typically Apache via .htaccess) for the other five security headers our Security Audit checks. This guide walks through every fix: enabling Joomla's HSTS, adding the rest via .htaccess, hardening session cookies, and publishing security.txt. Tested against Joomla 5.1 on Apache 2.4. For WordPress, see the WordPress variant; for the full finding catalogue, see Security Audit Fixes.

1. Enable Joomla's built-in HSTS

Joomla 4+ has a native HSTS feature you should use before adding HSTS via .htaccess — it integrates with Joomla's URL routing.

Step 1
Open Global Configuration
Joomla admin → System → Global Configuration → Server tab.
Step 2
Toggle HSTS
Set Force HTTPS to Entire Site. Set HTTP Strict Transport Security (HSTS) to Yes. Configure: HSTS Max Age 31536000, HSTS Apply to Subdomains Yes, HSTS Preload Yes. Save.
⚠️ Don't enable HSTS preload until you're certain every subdomain is on HTTPS. The browser preload list is hard to remove from once submitted.

2. Add the other five headers via .htaccess

Joomla doesn't manage CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy or Permissions-Policy natively. Add them to the root .htaccess:

Step 1
Locate .htaccess
Joomla root contains htaccess.txt (template) and .htaccess (active file). If .htaccess is missing, rename htaccess.txt to .htaccess first.
Step 2
Add the directives
At the top of .htaccess:
<IfModule mod_headers.c>
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
  Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'self'"
</IfModule>
💡 Joomla extensions often inject inline scripts. The CSP above includes 'unsafe-inline' for script-src and style-src — restrict this once you've identified all extensions that need it.

3. Harden session and cookie settings

Joomla's session cookies need the Secure and HttpOnly flags. SameSite needs configuration in Global Configuration.

Step 1
Session settings
System tab → Session Settings → Session Handler: Database. Force HTTPS: Entire Site (Server tab).
Step 2
Cookie SameSite
System tab → Cookie Settings → Cookie SameSite: Lax (recommended default). Save.

4. Publish security.txt

Step 1
Create the file
Create .well-known/security.txt in the Joomla root:
Contact: mailto:security@yourdomain.com
Expires: 2027-05-18T00:00:00.000Z
Preferred-Languages: en
Canonical: https://yourdomain.com/.well-known/security.txt
Add to .htaccess:
<Files "security.txt">
  ForceType text/plain
</Files>

5. Verify

Step 1
Curl test
curl -sI https://yourdomain.com/ | grep -iE "strict-transport|x-frame|x-content|referrer|permissions|content-security"
All six should appear. Then re-run the Security Audit.

🛡 Re-run the audit

Verify every header, TLS protocol and security.txt with a fresh scan.

Run Security Audit →
Related Guides: Security Audit Fixes  ·  Fix in WordPress  ·  Fix in Drupal  ·  Security Audit Guide
💬 Got a problem?