Let’s be honest. How many times have you opened Finder on your Mac, searched for a file, waited for results, and wondered why something so basic still feels unnecessarily complicated?
Apple’s Finder has been around for decades. It does its job, but if you work with hundreds or thousands of files, manage development projects, handle large media libraries, or regularly move files between folders, you might find yourself wishing it could do a little more.
What if you could have faster search, better file management, detailed disk usage insights, developer-friendly tools and a more powerful browsing experience without paying for another application?
That’s where Strata Files comes in.
Strata Files is a free, open-source file manager for macOS that aims to make managing files faster, smarter and more enjoyable. It takes the familiar experience of Finder and adds features that many Mac users have been waiting for.
And yes, it is completely free.
What Is Strata Files?
Strata Files is a native macOS file manager designed as an alternative to Apple’s Finder.
It combines familiar file management features with powerful capabilities such as instant file search, real-time folder sizes, disk usage visualization, dual-pane browsing, advanced filtering and developer tools.
But there’s something particularly interesting about Strata Files: it is built entirely using Apple’s native AppKit and Swift technologies.
There is no Electron, no web views and no unnecessary layers running in the background.
It is designed specifically for Mac users who want a fast, lightweight and privacy-focused experience.
Even better, Strata Files is open source under the MIT license. You can download it, use it, inspect its source code and contribute to its development.
Why Look for a Finder Alternative?
Finder is convenient, familiar and deeply integrated into macOS. However, convenience doesn’t always mean efficiency.
Consider a few everyday situations.
You want to find every PDF modified last month.
Your Mac is running out of storage, but you have no idea which folders are consuming the most space.
You need to compare two project folders and move files between them.
You want to search for files larger than 1 GB.
You work with multiple repositories and frequently navigate between project directories.
These are relatively simple tasks, but they can become frustrating when your file manager doesn’t provide the right tools.
Several third-party applications attempt to solve these problems, but some come with paid licenses, subscriptions or additional complexity.
Strata Files takes a different approach: deliver a powerful Finder alternative that is free and open source.
7 Reasons to Try Strata Files
1. Lightning-Fast File Search
Searching for files shouldn’t feel like waiting in a queue.
Strata Files indexes files in your home folder and Applications directory, allowing you to search as you type. Once indexing is complete, results can appear in milliseconds, even across millions of files.
You can search using file names, precise filters or natural language.
For example:
“PDFs from last month”
“Videos bigger than 500 MB”
ext:swift modified:<7d
size:>1gb kind:movie
You can even save searches and keep them available for later.
If you regularly work with large collections of documents, images, videos or development files, this feature alone is worth exploring.
2. Finally Understand Where Your Disk Space Goes
Running out of storage on your Mac?
Instead of manually opening folders and checking their properties, Strata Files provides a dedicated Disk Usage view.
It visualizes folder sizes using a map, making it easier to identify which directories are consuming the most storage.
You also get dedicated Large Files and Duplicates sections to help identify unnecessary files and reclaim valuable disk space.
This is particularly useful for developers, designers, photographers and video editors who regularly work with large files.
3. A Keyboard-First File Management Experience
If you love keyboard shortcuts, you’ll appreciate this.
Strata Files includes a command palette that lets you jump between folders, search files and execute commands without constantly reaching for your mouse.
Some useful shortcuts include:
Shortcut
Action
Command + K
Open command palette
Command + L
Type a path
Command + 1–5
Switch between views
Space
Quick Look
Shift + Command + F
Open Recents
You can also filter files within a folder simply by typing.
The goal is simple: spend less time navigating and more time getting things done.
4. Five Views and Dual-Pane Browsing
Different files deserve different ways of viewing them.
Strata Files supports five viewing modes:
Icons
List
Columns
Gallery
Disk Usage
It also includes Dual Pane mode, allowing you to work with two folders side by side.
Need to copy files from one project to another? Compare folders? Move documents between locations?
Dual Pane makes these operations much more convenient.
5. Powerful Features for Developers
This is where Strata Files becomes particularly interesting.
Most file managers focus primarily on everyday file operations. Strata Files goes further by offering tools designed for developers.
You can:
See Git status directly on files.
View the current Git branch in the path bar.
Run project scripts for Node.js, Rust, Swift, Python, Go and other technologies.
Preview Markdown, HTML, JSON, CSV and SQLite files.
Browse Docker and other container environments.
Connect to SFTP servers and S3 buckets.
Manage project files and inspect build artifacts.
For developers who spend most of their working day inside project directories, these features can make file management considerably more efficient.
6. Privacy Without Compromise
Privacy is another area where Strata Files stands out.
Your files are yours. Your file manager shouldn’t need to upload them somewhere else just to help you find them.
Strata Files runs locally on your Mac.
There are no accounts to create, no tracking and no cloud-based file indexing. Its search index and history are encrypted on disk, with the encryption key stored in your macOS Keychain.
Even its document summaries and AI-related features are designed to run locally.
That’s a meaningful advantage for people working with private documents, business files and development projects.
7. Completely Free and Open Source
Here’s perhaps the most interesting part.
Strata Files is free.
Not free for seven days. Not free with limited functionality. Not free until you need an essential feature.
The application is released under the MIT open-source license, and its website lists all its major features as included at no cost.
You can download it, use it, inspect the source code and contribute to its development.
For users looking for a free Finder alternative, that’s a compelling proposition.
Strata Files vs. Apple Finder
How does it compare with the file manager already installed on your Mac?
Feature
Apple Finder
Strata Files
Native macOS experience
Yes
Yes
Advanced instant search
Standard search
Yes
Natural-language search
Limited
Yes
Real-time folder sizes
Limited
Yes
Disk usage visualization
No built-in equivalent
Yes
Large files and duplicates
Limited
Dedicated tools
Dual-pane browsing
No
Yes
Git integration
No
Yes
SFTP and S3
No built-in support
Yes
Container browsing
No built-in support
Yes
Free
Yes
Yes
Open source
No
Yes
Strata Files is not necessarily intended to replace every feature of Finder. It is designed to work alongside Finder, giving users another way to manage their files.
You can even configure supported file-reveal workflows to open Strata instead.
Is Strata Files Really Free?
Yes.
Strata Files is released under the MIT license, and its website currently lists its complete feature set at $0.
There are no subscription plans or paid feature tiers advertised.
This includes advanced search, disk usage analysis, dual-pane browsing, developer tools, SFTP, S3, copy history, undo and on-device summaries.
For anyone searching for a free and open-source Finder alternative, this makes Strata Files worth considering.
Step 2: Select Download for Mac to access the latest release on GitHub.
Step 3: Download and install the application.
Step 4: Follow the initial setup instructions. You can optionally grant Full Disk Access to allow Strata to search and measure files across your Mac.
You can also install it using Homebrew:
brew install --cask cristipufu/tap/strata
Important: Strata Files currently requires a Mac with Apple silicon running macOS 26 Tahoe. It is not currently advertised as compatible with Intel Macs or older macOS versions.
Who Should Use Strata Files?
Strata Files is particularly interesting for:
Developers: Git integration, project inspection, terminal commands and container browsing.
Designers: Better file organization, gallery previews and large-file discovery.
Content creators: Managing large video, audio and photography libraries.
Power users: Keyboard shortcuts, advanced search and dual-pane browsing.
Privacy-conscious users: Local processing without accounts or cloud-based file indexing.
Open-source enthusiasts: A free application with publicly available source code.
If you regularly work with files on your Mac, there is a good chance you’ll find something useful here.
Final Verdict: Is Strata Files Worth Trying?
A good file manager should make your computer easier to use, not introduce another layer of complexity.
Strata Files makes an interesting case for itself by combining the familiarity of Finder with features that go considerably further.
Its fast search, disk usage visualization, dual-pane interface, developer tools and privacy-focused architecture make it more than just another Finder replacement.
But perhaps its biggest advantage is its pricing.
You get a native macOS application, an extensive feature set and an MIT open-source license without paying a subscription.
If you’ve been searching for a Finder alternative that is powerful, private, free and open source, Strata Files deserves a place on your shortlist.
You don’t have to uninstall Finder or commit to anything. Download it, explore its features and see whether it fits your workflow.
About Strata Files: Strata Files is a free and open-source native file manager for Apple silicon Macs, built with Swift and AppKit. It offers advanced search, disk usage analysis, dual-pane browsing, developer tools and privacy-focused local processing.
A Joomla extension is installed but not working when files exist (or a zip succeeded) and the site still has no working feature: the package is undiscovered, the row is disabled, the database schema never ran, PHP is too old or too new, a menu type was never created, or a module instance was never published. “Installed” in the installer message is not the same as enabled, assigned, and given a menu item. This is a readiness checklist, not a 500 hunt and not a two-plugin conflict hunt.
If the administrator or site is a 500, stop: find which extension causes a 500. If two enabled add-ons fight, use extension conflict. If the zip never finished, stay in System → Install → Extensions and read the installer message. This page assumes the installer said success, or you uploaded files by SFTP, and the feature is still dead.
A green install is a database row and files. The feature still needs Discover or enable, schema, PHP, a menu type, and often a module you create by hand.
What you will learn
The difference between Upload, Discover, and Enable
How to see the extension in System → Manage → Extensions
When System → Maintenance → Database (Update Structure) is the real fix
How to match PHP version to the extension’s requirements
One check for Behaviour – Backward Compatibility on Joomla 5 (not a full compatibility essay)
Why a component can install with no menu item type until you create one
Why a package’s module is not on the page until you create and assign it
Check ordering, access, and that you enabled the right plugin in a package
Component enabled
Admin menu may show it
Create a menu item of that type for the site
Module type exists
You can pick it under New Module
New, publish, position, assignment
Schema out of date
Files newer than SQL
Maintenance → Database → Update Structure
Most “not working” tickets are the right-hand column, not a corrupt zip.
Step 1: Find the row in Manage Extensions
System → Manage → Extensions.
Search the extension name and the com_, mod_, plg_ element if you know it.
Confirm Status (enabled). A lock icon means protected core. Third-party rows should be enableable.
Open the details. Note type (component, module, plugin, package, library, file).
A package installs several rows. The component can be enabled while the plugin that injects the feature is disabled. Filter by the package name and enable every non-core row the vendor documents.
If the search is empty, the installer did not register the extension. Either the zip failed silently (host upload limit) or someone copied folders by FTP. Go to Step 2. Do not keep uploading the same zip on top without checking Discover.
Step 2: Discover is not Enable
Discover is for files already on the server that Joomla does not have in #__extensions. Official help: Extensions: Discover.
Use it when:
The package was too large for the web uploader, so you extracted into components/com_example, administrator/components/com_example, media/com_example, and language folders as the installing guide describes.
A deploy process copied a git checkout of an extension into those paths.
Then:
System → Install → Discover (some sites label this under Manage → Discover).
Toolbar Discover.
Tick the extension. Install.
Discover does not turn a disabled plugin on. It creates the row. Then you enable in Manage Extensions or Plugins.
If Discover finds nothing, the files are in the wrong tree (nested extra folder, or site files only without administrator files). Fix the paths. Do not invent a second copy under tmp/ and expect Joomla to see it.
Normal small zips should go through System → Install → Extensions (upload). Discover is the exception path.
Step 3: Enable the plugin (packages hide this)
System → Plugins. Search the vendor or feature name.
Many components ship:
A system plugin that loads language or routing
A content plugin that prints a button or shortcode
An actionlog or privacy plugin you can leave off
If the system plugin is disabled, the component admin screen may open and the site view stays empty. Enable it. Then check Access on any module the package added.
Installer sample data sometimes creates an unpublished module. Published component + unpublished module = “not working” on the frontend.
Step 4: Fix the database schema
If the Home dashboard warns that the database is out of date, or the extension errors about a missing table or column:
System → Maintenance → Database.
If problems are listed, select the extension and Update Structure.
That replays skipped SQL. It is the documented fix after a partial Joomla or extension update: Version update, database check.
If Update Structure fails, the extension’s sql/updates files may not match the database engine, or a previous update died. Restore a backup and reinstall on staging. Do not create tables by hand unless the vendor gives you SQL.
A component that “installed” but never ran install.sql (Discover on incomplete files, or a failed package) will 500 or show empty lists. That can look like “not working.” Check error_log if the view fatals: 500 article.
Step 5: Match PHP version (and host extensions)
Open System → System Information (site and PHP tab). Note PHP version.
Open the extension’s documentation for minimum PHP and maximum tested. Joomla 5 itself needs a current PHP (see technical requirements for the Joomla version you run). An add-on that last shipped for PHP 7.4 will not run on PHP 8.3.
Also check System → Manage → Warnings and System Information for missing PHP modules (intl, gd, mbstring, zip). The installer may have succeeded while runtime needs curl for an API.
Host “PHP selector” can differ between the site and CLI cron. A plugin that works in admin and fails on cron is often two PHP versions.
Step 6: One Joomla 5 compatibility plugin check
On Joomla 5, core ships Behaviour – Backward Compatibility (plg_behaviour_compat). It loads Joomla 4 class aliases so older extensions can run. Official note: Compatibility plugin.
Check, do not redesign your stack around it:
System → Plugins, search Backward Compatibility or compat.
If a Joomla 4-era extension is installed and this plugin is disabled, enable it on a staging copy first and test. The Joomla docs warn that disabling it on production can fatal old extensions, and that you may need the database to turn it back on.
If you are preparing Joomla 6, this plugin must be disabled before that upgrade, and you need extensions that do not rely on it. That is an upgrade project, not this article.
This is one checkbox in the “installed but dead” list. It is not a substitute for a vendor’s Joomla 5 build. Prefer an updated extension. Do not treat the compat plugin as a permanent architecture.
Joomla 5.4 also installs Behaviour – Backward Compatibility 6 for the later jump. Do not disable that in a way the Joomla 6 migration guide forbids. Read Compatibility plugins (5.4 to 6) when you upgrade. For “not working today on Joomla 5,” the plg_behaviour_compat enable check is enough.
Step 7: Create the menu item (missing menu type)
A component can install a menu item type (Articles → Archived Articles is the core example). Your add-on is the same. Until you create Menus → your menu → New and select that type, the site has no URL.
Symptoms:
Administrator component works. Frontend 404 or Home never changes.
You look for a module. The feature is a component view, not a module.
The type is missing from the New Menu Item list: the component is disabled, Discover never ran, or the XML submenu / menu section failed. Reinstall or Discover. Confirm the component is enabled in Manage Extensions.
Create the menu item, set Access, set a template style if needed, save. Open that URL. Do not expect the installer to inject a menu item on a production menu. Many packages do not.
If the type appears but the view is empty, you may still need to create records inside the component (a first category, a first item). That is configuration, not a failed install.
Step 8: Create and publish the module
System → Site Modules → New. If the module type is in the list, the module type is installed. A type in the list is not an instance on the page.
Packages often do not create a published module. You must:
New → pick the type.
Set Position to a name the template actually prints (position not showing if the slot is empty everywhere).
Menu Assignment (wrong pages if it appears in the wrong place).
Publish. Public access. Language All or the right language.
If the type is not in New Module, the module file never installed (package incomplete, or you only installed the component zip). Install the full package. Discover if you dropped modules/mod_example by hand.
Editor buttons (editors-xtd) are plugins, not modules. Enable them under Plugins. They will not appear as Site Modules.
Language, ACL, and cache (short)
Install the extension’s language pack if the vendor ships one, or you will see KEY_NAMES as titles. For core string tweaks, language overrides.
Super User sees a module a Guest does not: Access.
Clear cache after enable. Page cache can hide a module you just published.
Custom fields inside an extension are not core article fields. Core article fields have their own empty-frontend guide: custom fields not showing.
Warnings, update sites, and a second install attempt
System → Manage → Warnings (or Installer warnings) lists environment problems Joomla already detected: PHP version, missing modules, memory. If a warning names the same constraint the vendor lists, fix the host before you reinstall the zip. Reinstalling will not add intl.
System → Update → Update Sites (or Manage → Update Sites): if the extension installed from a URL and later “does nothing” after you expected a patch, Rebuild the update sites, then System → Update → Extensions. An old build that “installed fine” on Joomla 5 can still be a Joomla 4 package. The update site is how you learn a Joomla 5 zip exists.
If you install twice, Joomla may refuse or may leave the first schema in place. Prefer Uninstall (after a backup) then install the matching Joomla 5 package, over copying folders on top of a half Discover. Uninstall removes #__extensions rows. It can drop the extension’s tables. That is why the backup exists.
A library or file package can install with no admin menu. The feature then lives inside another component. Read the vendor’s “where to click after install” once. Searching Site Modules for a library is a dead end.
Files and a green installer are the start. Enable, schema, PHP, menu type, and a published module instance are the rest.
Key takeaways
Installer success means a registry row. It does not mean enabled, schema-current, or on a menu.
Discover registers FTP-copied files. Enable turns plugins on. They are different buttons.
Packages hide a disabled system plugin. Search Plugins after every component install.
Maintenance → Database → Update Structure when files and SQL diverged.
Check PHP version and System Information warnings before you blame Joomla.
On Joomla 5, confirm Behaviour – Backward Compatibility if the add-on is old. Prefer a native Joomla 5 build. This is one check, not a strategy.
Components need a menu item type you create. Modules need a New instance, position, and assignment.
If it 500s, leave this checklist and read the log. If it works alone and fails with a neighbour, that is a conflict.
When a vendor package is registered but the live site still has no menu, no module, and no plugin enabled, a maintainer can finish the wiring: Joomla support and maintenance.
Frequently asked questions
Why is my Joomla extension installed but not working?
The zip registered files, but a plugin is still disabled, Discover was skipped after an FTP copy, the schema is behind, PHP does not match, or you never created a menu item or module instance.
What is the difference between Discover and Enable?
Discover finds manifests on disk and creates #__extensions rows (then you click Install on that screen). Enable turns an existing row on. Uploading a zip uses Install Extensions, not Discover.
Do I always get a module on the page after install?
No. You often get a module type. You still click Site Modules → New, publish it, and assign a position and pages.
Why is there no menu item type for my component?
The component is disabled, not fully discovered, or you are looking at the wrong client (site vs administrator). Enable the component, run Discover if files were copied, reinstall the package, then Menus → New.
Should I disable the Joomla 5 compatibility plugin to test?
Only on staging, and only if you can re-enable it in the database when admin dies. For an old extension that is “not working,” try enabling the plugin first. Plan a real Joomla 5 build before Joomla 6.
Update Structure did nothing. Now what?
Confirm you selected the extension that listed errors. If SQL still fails, restore a backup and reinstall on staging. Do not drop random tables on production.
Could this be a template problem?
Yes, if it is a module in a position the template does not print, or an override that errors. Check position names and child-template overrides after the extension is enabled and assigned.
Last updated Oct 21, 2026. We will update this guide as hosts and Linux vendors ship fixed packages.
Short answer: PHP2Shell is the name for two critical flaws in PHP itself, CVE-2026-109618 and CVE-2026-109619. Both are rated CVSS v4.0 9.2 and can let an attacker run code on your server without logging in. The only complete fix is to run PHP 8.2.35, 8.3.36, 8.4.27 or 8.5.12 or newer, released on 21 October 2026 (php.net advisory). Nothing in Joomla or WordPress fixes it, and no plugin or extension does either. If your site runs PHP 8.1 or older, there is no official fixed release: you need to move to PHP 8.3 or later, or get a patched package from your Linux vendor.
The fix in five steps: 1) find the PHP version your site actually serves, 2) get it onto a fixed build, 3) confirm the fix is really running, 4) add the interim hardening if you are still waiting, 5) plan an exit if your host will not move. Each step has its own section below, with steps for cPanel, Plesk, CloudLinux, VPS servers, Joomla 4, 5 and 6.2, and WordPress.
What is PHP2Shell, in plain English?
PHP is the engine that runs Joomla and WordPress. Every page of your site, from the home page to the admin login, is built by PHP on your web server. PHP is installed by your hosting company, not by you and not by your CMS.
PHP2Shell is a fault in that engine. A stranger can send your server one specially crafted web request, just like a normal visit but built to trigger the fault. The server can then run the stranger’s commands. No password is needed and no account is needed.
Because the fault sits in PHP, it hits before Joomla or WordPress even starts. Your admin password, two-factor login, security plugin or Joomla access rules never get a say. php.net confirms there is a working attack that triggers before any application code runs on the most common Apache setup.
An analogy: your Joomla or WordPress security is the lock on your apartment door. PHP2Shell is a broken lock on the building’s front door, and it opens the service corridor behind every apartment. A better apartment lock does not help. The building manager, your host, has to replace the front-door lock, which here means installing the fixed PHP release.
What can happen to your site if you ignore it?
Running commands on your server means an attacker can do roughly what your site itself can do. These are the usual results of that kind of access on any hacked site, not specific reported PHP2Shell cases:
Defacement. Your pages are replaced or altered with the attacker’s content.
Hidden malware or spam. Code is slipped into your files or database that redirects visitors, shows spam links or infects visitors’ browsers.
Stolen data. The site can read its own database, so customer details, orders, contact form submissions and user accounts can be copied.
Your server attacks others. The site is used to send spam email, host phishing pages or attack other websites, often without you noticing.
Google warnings and lost rankings. Google may label the site This site may be hacked in search results or show a red browser warning, and visitors and rankings drop while that lasts. See Google’s Security Issues report help.
Hosting suspension. Hosts commonly suspend accounts that send spam or host malware, which takes the whole site offline.
Cleanup cost and downtime. Removing malware, restoring backups, resetting every password and asking Google for a review takes time and money, and data that was stolen cannot be taken back.
If you sell online, handle bookings or collect personal data, a breach can also bring legal duties to report it to customers or regulators, depending on where you and they are.
Which PHP versions are safe, and which are not?
Check the first two numbers of your PHP version (the branch), then the last number (the patch level). Versions are from the PHP 8 changelog, the CERT-FR alert and NVD; support dates are from php.net’s supported versions and end-of-life pages.
Your PHP branch
Vulnerable
Fixed in
Branch support (php.net)
What you do
8.5
8.5.11 and below
8.5.12
Active support to 31 Dec 2027
Update to 8.5.12
8.4
8.4.26 and below
8.4.27
Active support to 31 Dec 2026, security to 31 Dec 2028
Update to 8.4.27
8.3
8.3.35 and below
8.3.36
Security fixes only, to 31 Dec 2027
Update to 8.3.36
8.2
8.2.34 and below
8.2.35
Security fixes only, ends 31 Dec 2026
Update to 8.2.35, then plan 8.3+
8.1
All
No official release
End of life since 31 Dec 2025
Move to 8.3+ or use a vendor backport
8.0, 7.x, 5.x
All
No official release
End of life
Move to a supported branch
8.6 release candidates
Not covered by the fixed releases
None yet
Testing only, not for production
Do not run in production
The PHP team also published minimal source-only patches for 7.4, 8.0 and 8.1 for people who compile PHP themselves. They are not releases, and a shared hosting panel cannot offer them.
Still on Joomla 3? Why patching PHP is not an option
This is the hardest case, and it is worth being precise about. Joomla’s official technical requirements list PHP 8.0 as the recommended version for Joomla 3.x, and no newer PHP version is listed. Joomla 3 support ended on 17 August 2023, and the extended LTS version ended on 17 February 2025, so Joomla 3 gets no more updates to make it work on newer PHP. Joomla volunteers on the official Joomla forum report that 3.10 does not work on PHP 8.2 or later and is unreliable on 8.1. Every branch that received the PHP2Shell fix is 8.2 or newer. Put those facts together and no officially supported Joomla 3 setup can run a patched PHP release.
What about the stopgaps? Each one helps a little and costs something:
Option
What it gets you
Where it falls short
Source-only backports for 7.4, 8.0, 8.1
The PHP2Shell fix for people who compile PHP themselves
No releases and no binaries. Shared, reseller and most managed hosts cannot install them, and you take on maintaining a custom PHP build.
Vendor or distribution backport (for example a Linux LTS package)
A patched PHP 8.0 or 8.1 from a vendor
Only on servers you or your host control at the OS level, often paid, and only covers PHP. Joomla 3 itself still gets no security fixes.
Interim php.ini settings and a WAF
Fewer known attack paths
php.net says they do not make an installation safe, and WAF rules can be bypassed by direct-to-origin traffic.
Forcing Joomla 3 onto PHP 8.2+
A patched PHP
Unsupported: expect white pages, 500 errors and broken extensions, which is why hosts that move clients forward often break Joomla 3 sites.
So the risk of staying is not only PHP2Shell. It is that every future PHP or Joomla vulnerability lands on a site with no supported fix. The lasting fix is to move the site to Joomla 6.2, which requires PHP 8.3 or newer, so it runs on a branch that gets security releases until at least the end of 2027. Joomla does not allow skipping straight from 3 to 6: the path is 3.10 → 4.4 → 5.x → 6.x, and our Joomla 3 to 6 upgrade guide walks through each hop. Run the free Joomla 6 compatibility check first to see which extensions have Joomla 6 versions and which need replacing; that list is what decides how long the move takes. If you would rather have the migration done for you, that is what our Joomla upgrade service covers.
Old WordPress on PHP 7.4 or 8.1? WordPress is gentler: current WordPress still runs on PHP 7.4 but recommends 8.3 or greater. Update WordPress core, plugins and themes first, then switch the branch as in Step 2b. Plugins abandoned by their authors are the usual blocker, so replace them before the switch.
How do the two flaws work?
Both flaws are about what PHP leaves behind when a web request ends badly. According to the NVD descriptions supplied by the PHP security team:
CVE-2026-109618: when PHP runs out of memory mid-request, some internal request memory can be left uninitialised. The cleanup step then reads it as if it were valid, and several out-of-memory tricks can turn that into remote code execution.
CVE-2026-109619: some global state can keep pointing at request memory after it has been freed. A later request on the same PHP worker can read that stale state before it is reset, which can also lead to remote code execution.
php.net says the risk covers all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, and is highest for mod_php, where a demonstrated exploit runs before any application code. For a Joomla or WordPress site this means your login page, security extension and file permissions are not in the way: the attack happens one layer below the CMS.
Fact
Detail
Source
CVSS v4.0 score
9.2 for both CVEs (vector AV:N/AC:H/AT:P/PR:N/UI:N)
Step 1: How do I check which PHP version my site really runs?
Check the version the web server uses for your site. The command-line php -v on the same server can be a different build, so do not rely on it alone.
In Joomla 4, 5 or 6.2
Log in to the Administrator, open System → System Information, and read PHP Version on the System Information tab. The PHP Information tab shows the full phpinfo output, including the Server API line (for example FPM/FastCGI or Apache 2.0 Handler), which tells you whether you are on the higher-risk mod_php.
In WordPress
Go to Tools → Site Health → Info and expand Server. The PHP version and Server API rows are listed there (WordPress Site Health docs).
With no admin access
Upload a one-line file, open it in the browser, note the version, and delete it immediately, because phpinfo output helps attackers:
<?php echo PHP_VERSION, " ", PHP_SAPI;
Name it something random (not info.php). It prints the exact version and the server API, for example 8.3.36 fpm-fcgi. PHP manual: phpversion()
Checking many sites
Repeat the same check per site, because one hosting account can run different PHP branches per domain. Record domain, branch, patch level and Server API in a sheet, and sort by the table above.
Step 2: How do I update PHP to a fixed version?
Two different things are called “updating PHP”. A patch update (8.3.35 to 8.3.36) is a drop-in security fix that your host installs on the server. A branch change (8.1 to 8.3) is something you usually select yourself and must test, because extensions and plugins can break. PHP2Shell needs the patch update everywhere, and a branch change if you are on 8.1 or older.
cPanel (shared hosting)
Open Software → MultiPHP Manager (cPanel docs), or Select PHP Version on CloudLinux servers.
Check which branch your domain uses. The selector picks a branch; the patch level inside it is whatever the host has installed.
If you are on 8.1 or older, take a backup, then pick 8.3 or newer and test the site (see Step 2b).
Run the Step 1 check again. If the patch level is still below the fixed build, open a ticket (template in Step 5).
Server admins with WHM install the fixed EasyApache 4 packages through the normal system update and manage versions in MultiPHP Manager for WHM.
Plesk
In Plesk, open the domain, then PHP (PHP Settings), and choose the PHP version. Plesk’s own advisory (updated 21 Oct 2026, 15:13 UTC / 8:43 PM IST) lists the state of its PHP builds:
Plesk PHP
Linux
Windows
8.2
Fixed in 8.2.35
In development
8.3
Fixed in 8.3.36
In development
8.4
Fixed in 8.4.27
In development
8.5
Fixed in 8.5.12
In development
7.4, 8.0, 8.1
In development
In development
To see which builds a Plesk server has, go to Tools & Settings → PHP Settings; the version is part of each handler name. On Linux over SSH, /opt/plesk/php/8.3/bin/php -v shows it (swap 8.3 for your branch).
Plesk also lists its own panel engine (sw-engine) as affected on all versions, with hotfixes planned as 18.0.80#11 and 18.0.81#4. If you run Plesk on Windows, use the interim hardening in Step 4 until the builds ship, and keep checking Plesk’s advisory.
CloudLinux, LiteSpeed and other managed hosts
On CloudLinux, the per-site PHP selector uses CloudLinux’s own alt-php builds, so the patch arrives when CloudLinux ships it and your host installs it. LiteSpeed is named in php.net’s list of affected setups. On managed WordPress and Joomla hosts with no PHP setting, the host alone controls the patch: ask for the exact version and date (Step 5).
Your own VPS or dedicated server
Distribution packages (Ubuntu, Debian, RHEL and clones): install the vendor security update with your normal package manager. Distributions often backport security fixes without changing the upstream version number, so confirm with the vendor’s security notice for these CVE IDs, not by version string alone.
Third-party repositories or source builds: upgrade to the fixed upstream release from php.net downloads or your repository once it publishes the build.
Docker images: pull an image built on the fixed release, rebuild, and redeploy every container; a running container never patches itself.
Then restart PHP (Step 3). Without a restart the old code keeps serving requests.
Step 2b: Moving off PHP 8.1 or older without breaking the site
Still on Joomla 3? PHP cannot move until Joomla does; see the Joomla 3 section.
Step 3: How do I confirm the patch is actually live?
Repeat the Step 1 check through the website (Joomla System Information, WordPress Site Health or the one-line file). The version must be 8.2.35, 8.3.36, 8.4.27, 8.5.12 or higher, or a vendor package your vendor confirms fixes both CVEs.
On a server, restart every PHP process: restart PHP-FPM pools, and for mod_php restart Apache fully. php.net’s advisory tells admins to restart every worker for settings to apply; the same applies to new binaries.
Check that no process still uses the old library. On Linux this should print nothing:
Then check every site on the account, not just the main one; add-on domains can run different branches.
Step 4: What can I do while I wait for my host?
php.net lists interim measures that reduce exposure to specific attack paths but, in its words, do not make an installation safe. They must be set in php.ini, the PHP-FPM pool or the web server config, which apply before the request is parsed. php.net says not to rely on ini_set() or FPM .user.ini.
Setting
Targets
Notes from php.net
session.upload_progress.enabled=0
CVE-2026-109619
Blocks the confirmed session paths, not other variants. Neither Joomla nor WordPress core needs it.
fatal_error_backtraces=0 (PHP 8.5 only)
CVE-2026-109619
Blocks the confirmed fatal backtrace path only.
memory_limit=-1 set with php_admin_value
CVE-2026-109618
Removes the controllable memory-limit failure; use a container or cgroup limit instead, not RLIMIT_AS or RLIMIT_DATA.
post_max_size = 8M (no uploads) or 32M (uploads), upload_max_filesize lower
CVE-2026-109618
Also cap request size, field count, multipart parts, headers and nesting at the web server or proxy.
Remove invalid or deprecated per-request settings (for example in .htaccess)
CVE-2026-109619
Hiding errors with display_errors or error_reporting does not help.
A Joomla site with large media uploads or a WordPress shop importing big CSV files may need the 32M limit. Our Joomla .htaccess guide shows where per-directory PHP settings live, so you can find and remove deprecated php_value lines.
Does Cloudflare or a WAF protect me?
Partly. Cloudflare says customers using its free or paid WAF have been protected by default against known PHP2Shell attacks since 21 Oct 2026, 03:02 UTC (8:32 AM IST), and still tells customers to patch PHP (Cloudflare blog). A WAF only helps if attackers cannot reach your server directly by IP, so restrict the origin to Cloudflare’s IP ranges. Treat any WAF rule as a stopgap.
Step 5: What if my host will not update PHP?
Send a short ticket that leaves no room for a vague answer:
Subject: PHP2Shell (CVE-2026-109618 / CVE-2026-109619) patch date
Hi, my site [domain] runs PHP [version]. PHP released 8.2.35, 8.3.36,
8.4.27 and 8.5.12 on 21 October 2026 to fix two unauthenticated remote
code execution flaws (https://www.php.net/). Please confirm:
1. the date the fixed build will be installed for my account, and
2. if you use vendor-backported packages, the package version that
includes both fixes.
If my branch (8.1 or older) will not be patched, which supported
branch can I switch to today?
Thanks.
If the host cannot give a date, or only offers PHP 8.1 or older, that is a reason to move. Until then, put the site behind a WAF with the origin locked down, apply what Step 4 allows on your plan, and keep fresh offsite backups. CERT-FR’s advice for unsupported versions is to isolate affected systems and migrate to a maintained version (CERT-FR), and BleepingComputer reports that the UK NCSC told organisations to update or take systems offline until patched (BleepingComputer).
Step 6: How do I know if my site was already attacked?
The flaws allow code execution as the web server user, so look for what an attacker would leave behind:
New or changed PHP files in upload, cache, images or tmp folders, especially since 20 Oct 2026.
Unknown administrator or Super User accounts.
Unusual POST requests, very large multipart uploads, or bursts of 500 errors in the access and error logs around 20 and 21 October.
Unexpected cron jobs, outbound connections or spam sent from the server.
Recorded PHP version and Server API for every site
☐
Every site on 8.2.35, 8.3.36, 8.4.27, 8.5.12 or a vendor-confirmed backport
☐
PHP-FPM / Apache restarted, no deleted libraries in use
☐
Sites on 8.1 or older scheduled for a branch change
☐
Interim settings applied where still unpatched
☐
Logs and files checked for signs of compromise
☐
Host ticket answered with a patch date
The short version
Find the PHP version every site really serves, get it onto 8.2.35, 8.3.36, 8.4.27 or 8.5.12, restart PHP and check again. Use the interim settings only while you wait, and chase your host for a date. If a site is on Joomla 3 or PHP 8.1 and older, the patch you need is a version upgrade, and the sooner it is planned the less any future PHP flaw matters. If you want a second pair of hands, Infyways has worked on Joomla sites since 2010 and replies to enquiries within 12 hours; you can reach us here.
Frequently asked questions
What does PHP2Shell mean for a non-technical site owner?
PHP, the engine that runs Joomla and WordPress, has a fault that lets a stranger run commands on your server without logging in. Ask your host to confirm your site runs PHP 8.2.35, 8.3.36, 8.4.27, 8.5.12 or newer.
Can I patch PHP2Shell on a Joomla 3 site?
Not on a supported setup. Every fixed PHP release is 8.2 or newer, and Joomla 3.10 does not run on PHP 8.2+. Vendor backports and php.ini settings reduce risk only partly, so the lasting fix is upgrading to Joomla 6.2 via 4.4 and 5.x.
What is PHP2Shell?
PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical flaws in the PHP runtime rated CVSS v4.0 9.2. They can allow unauthenticated remote code execution on servers that serve web requests with PHP.
Which PHP versions fix PHP2Shell?
PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12, released on 21 October 2026. PHP 8.1 and older get no official release.
Do I need to update Joomla or WordPress?
No CMS update fixes PHP2Shell, because the flaw is in PHP. Keep the CMS updated anyway, especially if you need to move to a newer PHP branch.
Will a security plugin or extension protect my site?
No. php.net describes a demonstrated exploit that triggers before any application code runs, so CMS security plugins and extensions never see it.
Is PHP 8.1 safe if my host says it is patched?
Only if the host uses a vendor package that backports both fixes, and can name it. The PHP project itself published no fixed 8.1 release.
Which PHP version should a Joomla 6.2 site use?
Joomla 6 requires PHP 8.3 and recommends 8.4. Use 8.4.27 or 8.3.36 or newer.
Which PHP version should WordPress use?
WordPress recommends PHP 8.3 or greater. On 8.3, use 8.3.36 or newer.
Can I set the PHP2Shell mitigations in .user.ini?
No. php.net says not to rely on ini_set() or FPM .user.ini; use php.ini, the FPM pool or server configuration, then restart every worker.
Is Cloudflare enough to protect my site?
No. Cloudflare deployed WAF rules on all plans but still tells customers to patch, and a WAF does nothing for traffic sent straight to your server IP.
A Joomla 500 error means PHP or the web server aborted the request. The extension name is in the log, not in the generic “Whoops” page. Read error_log (and Joomla’s log folder), turn Debug on from Global Configuration or configuration.php, then isolate the last update. On a staging copy only, you can temporarily rename a plugin folder to prove the group. Never delete production files without a backup, and never “clean up” live plugins to find a 500.
The browser message is empty on purpose. Production hides fatals. Your job is to make the fatal visible in a log, then disable one extension, not the whole site.
The HTML is a dead end. The PHP error log is the map. The path under plugins, modules, or components is the extension.
What you will learn
Where hosts put error_log and where Joomla writes administrator/logs
How to enable Debug and Maximum error reporting when the admin still opens
How to set $debug and $error_reporting in configuration.php when admin does not
Why the last update is the first extension to disable
How to rename a plugins folder on staging only as a group test
How to disable one row in #__extensions without deleting files
Joomla 4 and 5 often show a page titled like Whoops, looks like something went wrong with an HTTP 500 status. That is still a server 500. A white screen is the same class of failure with display_errors off.
Source
What it is good for
PHP error_log (host panel, or a file in the account)
Fatals that happen before Joomla’s pretty error page
Web server error log (Apache/nginx)
.htaccess, PHP-FPM socket, permissions
administrator/logs/ (or the path in Global Configuration)
Joomla Log::add and some extension logs, not every fatal
Debug System + Error Reporting Maximum
Stack trace after Joomla has bootstrapped
Browser Network tab
Confirms 500 vs 403 vs timeout. Does not name the PHP file
If the log line is .htaccess or mod_security, you may not have an extension problem. Fix the server rule, then come back if PHP still fatals.
Step 1: Copy the site, then backup production anyway
Before any rename, disable, or configuration.php edit on a live site:
Snapshot or copy files and the database (host backup, or your own). If you cannot restore, do not experiment on production.
Prefer a staging URL with the same Joomla and PHP versions. Do the hunt there. Deploy the known-good disable back to production.
Tell the team the site may be briefly noisy if you enable Maximum error reporting on production.
Do not delete the plugins directory on production “to see what happens.” You will take down authentication, two-factor, and SEF. You may not get admin back without a restore.
A file named error_log in public_html or in the account home
~/logs/error.log on some VPS stacks
Open the log at the timestamp of your test request. One line of PHP Fatal error is worth an hour of plugin guessing.
Copy:
The exception class (Error, TypeError, ParseError)
The file path and line
The first few frames of the stack if present
Map the path:
plugins/system/example/ → System plugin “example”
plugins/content/example/ → Content plugin
modules/mod_example/ → that module (unpublish it in Site Modules once admin works)
components/com_example/ → that component
templates/cassiopeia/ or a child → template PHP, often an override. See customize without editing core after the site is up.
libraries/ → core or a library package. Do not delete libraries. Restore a backup or revert the last Joomla update.
Joomla also logs under Global Configuration → System → Path to Log Folder (default administrator/logs). Check everything.php or dated files if the host PHP log is empty. Many fatals never reach Joomla’s logger because PHP died first. That is why error_log is step 2, not step 5.
Step 3: Debug from Global Configuration, or from configuration.php
If administrator still loads:
System → Global Configuration.
System tab: Debug System = Yes.
Server tab: Error Reporting = Maximum.
Save. Reload the failing site URL once (and the admin URL if that is what 500s).
Read the on-screen file and line. Then set Debug = No and Error Reporting = System Default. Save.
The Debug console is configured by System – Debug. Allowed Groups can hide the console from guests. You still want Maximum reporting for the fatal text.
If administrator is a 500 too, do not keep hitting login. Use FTP or the host file manager:
Download configuration.php. Keep a copy.
If the file is 444, set it to 644 long enough to edit (the manual describes this).
Set public $debug = true;
Set public $error_reporting = 'maximum';
Save. Reload once.
Put $debug back to false and $error_reporting back to 'default' or 'none' (match what you had) as soon as you have the path. Leaving Maximum on production leaks paths to visitors.
Optional: rename the template’s error.php on staging if that file is itself fataling and hiding the real message. Do that only on the copy.
Step 4: Disable the last update first
System → Update → Extensions (if admin works) or your change log:
Last extension update
Last Joomla update
Last PHP version change on the host (this 500s old extensions without a zip install)
Disable in this order once you have a path, or if the log is empty but the clock matches an update:
The extension named in the log.
If the log names a plugin, disable that plugin in System → Plugins (or #__extensions below).
If admin is down, you cannot click Plugins. Use the database: table #__extensions (your prefix), find element matching the plugin name, set enabled to 0. The user manual describes this for a faulty extension. Do not set core rows to 0 unless you know the row.
If the last change was a component update, disable its plugins first (packages register several rows). Then take the component off the default menu item so it is not the Home view.
Clear cache files on disk if page cache is on (cache/ folder) after a disable. A cached 500 is rare. A cached blank HTML is less rare. Still worth deleting cache/ on staging.
Step 5: Staging only, rename a plugins folder to test a group
This is a group proof, not a production technique.
On staging:
Confirm you can restore (snapshot, or a zip of plugins/ you just made).
Rename one third-party plugin directory, for example plugins/system/suspect → plugins/system/suspect.off. Joomla will skip that folder. Core plugins stay.
Reload. If the 500 is gone, that folder was in the path (or something it triggered was).
Rename it back. Disable the plugin properly in the database or UI so the site does not fatal on the next page that autoloads it in a different way.
You can rename a group folder on staging in an emergency, for example plugins/system → plugins/system.off, to see whether any system plugin is involved. That will break a lot of features. It is a binary test on a copy, then you put the folder name back immediately and disable one plugin at a time.
Do not do this on production. Do not delete the folder. Do not rename plugins as a whole on a live shop. You will remove authentication plugins and lock everyone out. If you already did that on production, restore the backup from Step 1. Do not invent a “fix” by uploading empty directories.
If you need a batch disable with the UI still up, that is the conflict article’s plugin batches, not a filesystem delete.
Step 6: Database disable when the UI is dead
phpMyAdmin or an SQL client, on a backup first:
Table: {prefix}_extensions
Find the row: type = plugin, element = the plugin name, folder = system/content/…
Set enabled = 0
For a module, you can also unpublish in {prefix}_modules (published = 0) if the log named mod_….
For a component Home page that 500s, change the default menu item in {prefix}_menu to a core featured or article view, or disable the component’s plugins, rather than DROP TABLE. Deleting tables is how you turn a 500 into a restore.
When admin returns, uninstall or roll back the extension with System → Manage → Extensions if you are done with it. Uninstall is not the same as deleting folders by hand. The installer cleans #__extensions rows.
Memory, timeouts, and logs that name PHP, not an extension
Some 500s never mention plugins/. They still belong to an extension.
Allowed memory size exhausted at a line in plugins/system/example/ is that plugin (or a loop it triggered). Raise memory_limit only on staging to confirm. On production, fix the plugin or the data set it loads (a module that queries every article is a typical case).
Maximum execution time exceeded in a component view is that component, or a plugin that runs on that view. Do not raise max_execution_time as the only fix.
PHP Parse error in an override under templates/…/html/ is your copy, not the vendor zip. Restore the core layout on staging, then repair the override in a child.
.htaccess 500s often follow a security plugin that wrote rewrite rules, or a hand edit after an extension installer. On staging, temporarily rename .htaccess to .htaccess.bak and use Joomla’s default htaccess.txt copied to .htaccess. If the 500 vanishes, the rules were the problem. Put your custom rules back one block at a time. Do that on production only after a backup, and only if you can restore via the host panel when you lock yourself out.
Gzip in Global Configuration plus Maximum error reporting can produce odd output on some hosts. If Debug shows a fatal and the browser still shows a generic 500, disable Gzip for the test. Turn it back on later.
After the site loads, close the hole
Set $debug false and error reporting off/default.
Set Preview and Debug plugins back to normal groups.
Update or replace the extension. If it needs old class names on Joomla 5, that is a compatibility check on the installed but not working article, not a reason to leave Debug on.
If a plugin tmpl was the fatal (parse error in an override), fix the override in a child. Plugin override.
Write the extension name and version in your runbook so the next 500 is shorter.
Log first. Last update second. Rename plugin folders only on staging. Never delete live files to “test.”
Key takeaways
A Joomla 500 is a server abort. The extension is named in error_log (or a Debug stack), not in the Whoops HTML.
Copy the site or take a full backup before you change configuration.php or plugin folders on anything you care about.
Enable Debug and Maximum error reporting only for the reproduce, then turn them off.
Disable the last updated extension first when the clock matches and the log agrees.
Rename plugin folders only on staging, as a temporary proof. Put the names back. Disable via Plugins or #__extensions.
Never delete production plugins/, components/, or libraries/ to debug. Restore from backup if you already did.
Database enabled = 0 on one extension row is the safe UI-down move. Dropping tables is not.
When two extensions work alone and 500 together, finish recovery then use the conflict process.
Frequently asked questions
How do I find which Joomla extension is causing a 500 error?
Read the PHP error_log at the request time. The file path under plugins/, modules/, or components/ is the extension. Enable Debug if Joomla still bootstraps. Then disable that extension, starting with the last update if the log is empty.
Can I rename the plugins folder on the live site?
No. Use staging. On production, take a backup and disable one #__extensions row, or restore. Renaming plugins on live removes authentication and can lock out admin.
Admin is a 500. How do I turn on debug?
Edit configuration.php: $debug = true and $error_reporting = 'maximum'. Reload once, copy the error, then turn both back off. The user manual documents the permission change if the file is read-only.
The error_log is empty. What next?
Check the web server log, Joomla’s log path, and whether you are looking at the right vhost. Enable Maximum reporting on staging. If PHP dies before logging, ask the host for the FPM log.
Should I delete the extension files to stop the 500?
No. Disable it. Deleting files on production without a backup is how you lose the only copy of a paid extension and still leave broken #__extensions rows. Restore, then uninstall from the administrator when it loads.
Could PHP be the “extension”?
A host PHP upgrade can fatal old extensions. The log still names the extension file. The fix is an update of that extension, or rolling PHP back on staging to prove it.
When is a 500 not an extension?
Disk full, bad database credentials in configuration.php, a broken .htaccess, or a core update that failed mid-way. The log still decides. If it names libraries/ after a Joomla update, restore the update backup, do not delete libraries.
Short answer: Joomla 6.2, released on 13 October 2026, added OAuth 2.0 (XOAUTH2) authentication for SMTP to core. Go to System → Global Configuration → Server → Mail, set Mailer to SMTP and SMTP Authentication to OAuth 2.0. Enter the Client ID, Client Secret, Scope, Authorize URL and Token URL from your mail provider and save. Then click Get OAuth2 Token and sign in to the mailbox. Joomla stores a refresh token instead of your SMTP password and fetches a short-lived access token each time it sends mail. The feature is generic, with no built-in presets, so it works with any XOAUTH2 provider. The Joomla manual documents Microsoft 365 and Gmail / Google Workspace, and this guide covers both.
In this guide: what 6.2 added (checked against the 6.2.0 code), why password SMTP is being retired, step-by-step setup for Microsoft 365 and Google, how to test it, a table of common errors and their fixes, and what to do if you can’t upgrade yet. Planning the upgrade itself? Start with our Joomla 6 guide.
What did Joomla 6.2 add to the mail settings?
The Joomla 6.2 release announcement lists “Generic XOAuth2 support for mail authentication”. It arrived through pull request #48290, which replaced an earlier proposal with provider-specific presets for Microsoft and Google with a generic version. We checked the 6.2.0 code so the field names below match what you’ll see.
Setting
What changed in 6.2
SMTP Authentication
Now a list instead of Yes/No: Disabled, Username and Password, OAuth 2.0. Existing sites keep their old setting.
OAuth2 Information
A note with the callback URL to register at your provider and a link to the Joomla manual.
SMTP Username
Still used with OAuth 2.0. It’s the mailbox Joomla signs in as. SMTP Password is hidden.
OAuth2 Client ID / Client Secret
Your app’s credentials from Microsoft Entra or Google Cloud. The secret field is masked and locked once saved.
OAuth2 Scope
The provider permission, such as https://outlook.office.com/SMTP.Send offline_access or https://mail.google.com/.
OAuth2 Authorize URL / Token URL
The provider’s OAuth endpoints. No presets are built in, so you paste them.
OAuth2 Token
Buttons for Get OAuth2 Token (or Reissue OAuth2 Token) and Validate Token, plus the time the token was issued.
Under the hood, Joomla asks for consent with prompt=consent and access_type=offline, so the provider returns a refresh token. It checks a random state value against your admin session when the provider redirects back, and only a Super User (core.admin) can save the token. When it sends mail, it hands PHPMailer an XOAUTH2 token provider that swaps the refresh token for an access token and caches it until about 60 seconds before it expires.
Which providers does it support?
Any SMTP server that accepts SASL XOAUTH2 with the OAuth 2.0 authorization code flow. The Joomla manual gives tested values for Microsoft 365 (Exchange Online) and Gmail / Google Workspace. For other providers you need their SMTP host, OAuth endpoints and the scope that allows SMTP sending. Joomla 6.2 doesn’t support Microsoft’s app-only client credentials flow (SMTP.SendAsApp). It signs in as a real mailbox.
Why is basic-auth SMTP being retired?
Basic authentication means the app stores and sends the mailbox username and password. Microsoft calls it vulnerable to credential theft, phishing and brute force attacks. OAuth tokens are limited to one app and one permission, they expire, and they keep working with multi-factor authentication turned on. These are the dates the providers have published:
Provider
What happens
When
Google (Gmail and Workspace)
Access for “less secure apps” turned off for all Google Accounts. SMTP, IMAP and POP stop working with passwords. Source
14 March 2025 (first-time connections blocked from summer 2024)
Google exception
App passwords still work where the account allows them. Google lists them as an option for devices that can’t use OAuth.
Current
Microsoft Exchange Online
No change to SMTP AUTH basic authentication yet.
Now until December 2026
Microsoft Exchange Online
SMTP AUTH basic auth disabled by default for existing tenants. Admins can still re-enable it. Source
End of December 2026
Microsoft Exchange Online
New tenants can’t use SMTP AUTH basic auth by default. OAuth is the supported method.
Tenants created after December 2026
Microsoft Exchange Online
Microsoft will announce the final removal date.
Second half of 2027
Microsoft had planned to start rejecting basic-auth SMTP on 1 March 2026. It put that on hold in its 27 January 2026 update. Treat the end of December 2026 as your real deadline for Microsoft 365, and plan your switch before then.
What do you need before you start?
Joomla 6.2.0 or later. Check System → System Information. On Joomla 5.4, the move to 6.2 is an upgrade, not a migration.
A Super User account in Joomla.
Admin access to the provider: a Microsoft Entra role that can register apps (and grant consent if your tenant needs it), or a Google Cloud project.
The mailbox Joomla will send from, with its password and MFA at hand for the one-time sign-in.
Your site’s exact admin URL, including https, www or not, and any subfolder. The callback URL must match it character for character.
Joomla builds it from the address you’re using to reach the administrator, so open the admin on the same host you register (for example, always www).
How do you set up Microsoft 365 / Outlook SMTP OAuth2 in Joomla?
Step 1: Register an app in Microsoft Entra
Open the Microsoft Entra admin center and go to Identity → Applications → App registrations → New registration (Microsoft guide).
Name it, for example Joomla SMTP. For one organisation, choose Accounts in this organizational directory only.
Under Redirect URI, choose platform Web and paste your Joomla callback URL. You can also add it later under Authentication.
Register, then copy the Application (client) ID and Directory (tenant) ID from the Overview page.
Step 2: Add the SMTP permission and a client secret
Under API permissions, add the delegated permission SMTP.Send (Microsoft’s scope string is https://outlook.office.com/SMTP.Send, per Microsoft Learn). Grant admin consent if your tenant requires it.
Under Certificates & secrets → Client secrets, create a secret and copy its Value straight away. Don’t copy the Secret ID. Microsoft shows the value only once.
Note the secret’s expiry date and set a reminder. When it expires, mail stops until you paste a new one and reissue the token.
Step 3: Make sure SMTP AUTH is allowed for the mailbox
OAuth won’t help if SMTP AUTH itself is switched off. In the Microsoft 365 admin center, go to Users → Active users, select the mailbox, then Mail → Manage email apps and tick Authenticated SMTP. Microsoft notes that if security defaults are on, SMTP AUTH is already disabled, and an organisation-wide setting can also turn it off (Microsoft Learn). In PowerShell:
Changes to the app, permissions or Exchange can take a while to apply. The Joomla manual suggests allowing up to about an hour before you decide something is broken.
Replace TENANT_ID with your Directory (tenant) ID. Keep offline_access in the scope. Without it Microsoft doesn’t return a refresh token and Joomla shows “Failed to acquire OAuth2 refresh token.”
Step 5: Save, then get the token
Click Save first, because Joomla reads the saved values when it starts the sign-in. Then click Get OAuth2 Token, sign in as the SMTP Username mailbox and accept the permission. You’re sent back to Global Configuration with “OAuth2 token received and saved.” and an issue time under the button.
Personal Outlook.com accounts: Microsoft says OAuth for SMTP works for Outlook.com too. The Joomla manual only documents the work-account setup above, though, and personal accounts need an app registration that allows personal Microsoft accounts. We haven’t covered that case here.
How do you set up Gmail or Google Workspace SMTP OAuth2 in Joomla?
Step 1: Configure the Google Auth Platform
In Google Cloud Console, create or pick a project for this site.
Open Google Auth Platform and fill in Branding (app name, support email, developer contact).
Under Audience, choose Internal if every sending mailbox is in your Workspace organisation. Choose External for a personal Gmail account.
Under Data Access, add the scope https://mail.google.com/. Google treats it as a restricted scope, which can mean extra verification for public apps. That usually doesn’t apply to an internal app used by your own staff.
Step 2: Create a Web application client
Go to Google Auth Platform → Clients → Create client and choose Web application. Google says to use this type for server-side apps (Google for Developers).
Under Authorized redirect URIs, add the full Joomla callback URL, query string included. Just the domain isn’t enough.
Copy the Client ID (it ends in .apps.googleusercontent.com) and the Client secret.
Step 3: Watch the 7-day trap on External apps
Google’s OAuth documentation says an External app whose publishing status is Testing gets refresh tokens that expire after 7 days. That applies to the Gmail scope. Your Joomla mail would work for a week and then stop with invalid_grant. For a personal Gmail account, add the mailbox as a test user only for the first try, then publish the app (move it to In production) before you rely on it. Workspace sites with an Internal app don’t hit this limit.
Step 4: Enter the values in Joomla
Joomla field
Gmail / Workspace value
Mailer
SMTP
SMTP Host
smtp.gmail.com
SMTP Port
587
SMTP Security
STARTTLS
SMTP Authentication
OAuth 2.0
From Email / SMTP Username
The same Google mailbox
OAuth2 Client ID
Your Web client ID
OAuth2 Client Secret
Your client secret
OAuth2 Scope
https://mail.google.com/
OAuth2 Authorize URL
https://accounts.google.com/o/oauth2/v2/auth
OAuth2 Token URL
https://oauth2.googleapis.com/token
Save, click Get OAuth2 Token, sign in with the same Google account and allow access. If Google shows an “unverified app” warning for your own External app, that’s expected while it’s unverified. Continue only if it’s your app.
How do you test that Joomla is really using OAuth?
Click Validate Token. A good result reads “Token is valid. Access token expires in N seconds.” This proves the refresh token works with your client ID and secret.
Click Send Test Mail. Joomla sends a message to your own Super User email address with the subject “Test mail from {your site name}”.
Read the success message closely. If it says the email was sent “using PHP Mail as fallback”, Joomla didn’t use SMTP. Fix the SMTP error before you go further.
Check that the message arrived and look at the headers. It should come from your provider’s servers.
Test a real flow too: a contact form, a password reset or a registration email.
Add this to your maintenance checklist: Microsoft client secrets expire, and Google revokes refresh tokens in some cases, for example if one goes unused for six months or the user changes their password while the token has Gmail scopes. The fix is the same each time: update the secret if needed, save, then click Reissue OAuth2 Token.
What do the common SMTP OAuth2 errors mean?
Error you see
Usual cause
Fix
AADSTS50011: redirect URI doesn’t match
The callback in Entra differs from the one Joomla sends (www vs non-www, http vs https, or a different admin path)
Copy the URL from the OAuth2 Information note into Entra exactly, and use the admin on that same host
AADSTS7000215: invalid client secret
The Secret ID was pasted instead of the Value, or the secret expired
Create a new secret, paste its Value, save and reissue the token
AADSTS65001 or “Need admin approval”
Your tenant requires admin consent for SMTP.Send
Have an admin grant consent under API permissions
535 5.7.139 Authentication unsuccessful
SMTP AUTH is off for the tenant or mailbox, or security defaults are on
Enable Authenticated SMTP on the mailbox and check the tenant setting
535 5.7.3 Authentication unsuccessful
SMTP Username isn’t the account that signed in, or the token lacks SMTP.Send
Match the SMTP Username to the mailbox you authorised and check the scope
554 5.2.252 SendAsDenied
From Email Address differs from the SMTP Username
Use the same address, or grant Send As in Exchange
Google Error 400: redirect_uri_mismatch
The callback isn’t in Authorized redirect URIs, or only the domain is
Add the full callback URL, query string included
Google Error 403: access_denied
External app in Testing and the account isn’t a test user, or an admin blocks the app
Add the test user or publish the app; Workspace admins can trust the app
Google invalid_grant after a week
External app still in Testing, so the refresh token expired after 7 days
Publish the app, then reissue the token
admin_policy_enforced
A Workspace admin restricted Gmail access for third-party apps
Ask the admin to allow or trust your OAuth client
Joomla: “The most recent request was denied because it had an invalid security token”
The callback reached a different session, for example you started on one host and came back on another, or the session timed out
Start again from Global Configuration on the exact host in the callback URL
Joomla: “OAuth2 authorize URL or client ID is missing.” or “OAuth2 token URL, client ID or client secret is missing.”
A field is empty, or the values weren’t saved before you clicked the button
Fill in the fields, save, then click Get OAuth2 Token
Joomla: “Failed to acquire OAuth2 refresh token.”
No refresh token came back (on Microsoft, usually a missing offline_access)
Fix the scope, save and reissue
Joomla: “OAuth2 SMTP configuration is incomplete.”
Username, client ID, secret, token URL or the stored refresh token is empty
Fill in every field and get a token
Microsoft lists every AADSTS code in its Entra error code reference. If a test mail fails and no clear error appears, turn on Debug System in Global Configuration for a moment, or check your server’s PHP error log. Turn debugging off afterwards.
Is it safe to store the refresh token in Joomla?
It’s safer than storing the password, but treat it the same way. Joomla 6.2 saves the client secret and refresh token with the rest of Global Configuration in configuration.php. Anyone who can read that file can send mail as the mailbox until you revoke the token. So keep the file outside public reach with strict permissions, don’t commit it to Git, and use a dedicated sending mailbox, not a person’s main account. If you think it leaked, revoke the app’s access (for Microsoft, delete the secret; for Google, remove the app from the account’s third-party access), then create new credentials. Our Joomla security guide covers file permissions and admin hardening.
What if you can’t upgrade to Joomla 6.2 yet?
Situation
Option
Trade-off
Joomla 5.x or 6.0/6.1
Upgrade to 6.2 for core OAuth
Test extensions first; 5.4 to 6.2 is an upgrade, not a migration
Google mailbox, can’t upgrade soon
A Google app password, where the account allows one
Still a stored password; Google lists it as an exception, not the goal
Microsoft 365, can’t upgrade soon
Basic-auth SMTP still works until end of December 2026
Plan the switch; after that it’s disabled by default
Any version
A transactional email service with API-key SMTP
Another vendor and DNS (SPF, DKIM) setup
Any version
A third-party Joomla OAuth mail plugin
Paid, and another extension to maintain
Upgrades aren’t always smooth. Our Joomla upgrade issues guide tracks known 6.2 problems and their workarounds.
Need help switching your Joomla mail to OAuth?
Infyways has built Joomla sites since 2010 and makes 125 Joomla extensions. We can upgrade you to 6.2, set up the Entra or Google app, move your mail to OAuth, check SPF, DKIM and DMARC so messages land in the inbox, and document how to renew the secret. See our Joomla development services. Send us your site and mail provider. We reply within 12 hours.
Yes, from Joomla 6.2.0 (released 13 October 2026). In Global Configuration → Server → Mail, set Mailer to SMTP and SMTP Authentication to OAuth 2.0, enter your provider’s client details and endpoints, save, and click Get OAuth2 Token.
Which Joomla version added OAuth 2.0 for email?
Joomla 6.2. Earlier versions, including Joomla 5.x, 6.0 and 6.1, only support username and password SMTP authentication in core.
What scope does Joomla need for Microsoft 365 SMTP?
Use https://outlook.office.com/SMTP.Send offline_access. SMTP.Send allows sending, and offline_access makes Microsoft return the refresh token Joomla stores.
What scope does Joomla need for Gmail SMTP?
Use https://mail.google.com/, with the authorize URL https://accounts.google.com/o/oauth2/v2/auth and the token URL https://oauth2.googleapis.com/token.
What is the redirect URI for Joomla SMTP OAuth2?
Your site URL followed by /administrator/index.php?option=com_config&task=mail.oauth2callback&format=raw. Register it exactly, with the same https and www as the admin URL you use.
Why did my Gmail OAuth stop working after 7 days?
Google issues 7-day refresh tokens to External apps in Testing status that request Gmail scopes. Publish the app, or use an Internal app on Google Workspace, then reissue the token in Joomla.
When does Microsoft turn off basic authentication for SMTP?
Under Microsoft’s January 2026 timeline, SMTP AUTH basic authentication is disabled by default for existing tenants at the end of December 2026. Admins can re-enable it for now, and Microsoft will announce the final removal date in the second half of 2027.
Do I still need an SMTP password with OAuth 2.0?
No. With OAuth 2.0 selected, Joomla hides the SMTP Password field and uses the stored refresh token. You still enter the SMTP Username, which must match the mailbox you authorised.
Short answer: no CMS is ADA compliant out of the box, and Joomla is no exception. Joomla 5 and 6 aim for WCAG 2.1 AA, ship a default template built with accessibility in mind (Cassiopeia) and include a built-in checker (jooa11y). Even so, an independent WCAG 2.2 AA audit of Joomla core, released in August 2026, found 42 issues. For US state and local governments, the ADA Title II rule requires WCAG 2.1 AA by 26 April 2027 or 26 April 2028, depending on population. Whether your site passes depends mostly on what sits on top of core: your template, your extensions and your content.
In this guide: a quick answer, what WCAG 2.2 adds, what Joomla core covers and what the 2026 audit flagged, the ADA rules for public entities and businesses, a 9-step audit-and-fix process, the tools to use, the truth about overlays and “ADA plugins”, and an FAQ. Selling to Europe? Read our European Accessibility Act guide as well. This article is general information, not legal advice.
Is Joomla ADA and WCAG compliant? The quick answer
Question
Short answer
Is Joomla ADA compliant out of the box?
No CMS is. Joomla core aims for WCAG 2.1 AA. Your template, extensions and content decide whether your site meets it.
Is Joomla WCAG 2.2 compliant?
Not yet. The August 2026 Axess Lab audit found 42 WCAG 2.2 AA issues in core, with 27 success criteria failed. The Joomla project is now planning and merging fixes.
Which standard should I target?
WCAG 2.1 AA is the legal standard under the Title II rule. Build to WCAG 2.2 AA, which also covers 2.1 AA.
When are the ADA Title II deadlines?
26 April 2027 for public entities with 50,000+ people. 26 April 2028 for smaller entities and special district governments.
Will a plugin make my site compliant?
No single plugin will. Checkers find issues and helpers patch some of them, but people still have to test and fix.
What should I do first?
Audit each page type, fix problems at the source, then re-test after every update.
What does WCAG 2.2 AA mean for a Joomla site?
The Web Content Accessibility Guidelines (WCAG) are the W3C standard behind almost every accessibility law. They sit under four principles, known as POUR. Content must be Perceivable (alt text, captions, enough contrast), Operable (everything works with a keyboard, with no traps and enough time), Understandable (clear labels, predictable navigation, helpful error messages) and Robust (clean markup that assistive technology can read). Level AA means meeting every Level A and AA success criterion. AA is the level that laws, regulations and settlements usually point to.
WCAG 2.2 became a W3C Recommendation on 5 October 2023. It adds nine success criteria to WCAG 2.1. Six of them are Level A or AA, so they count toward AA conformance; the other three are AAA. WCAG 2.2 also removes 4.1.1 Parsing as obsolete. Apart from that, the 2.1 criteria are unchanged, so building to 2.2 AA also covers the 2.1 AA standard in the Title II rule. Here are the six new A/AA criteria and where Joomla sites usually trip:
New criterion (level)
What it asks
Where Joomla sites trip
2.4.11 Focus Not Obscured (Minimum), AA
A focused element must not be completely hidden by content you added.
Sticky headers, cookie banners and chat bubbles covering the focused link.
2.5.7 Dragging Movements, AA
Anything done by dragging must also work with a single click or tap.
Drag-only sliders and sortable lists. The audit flagged drag-only article reordering in Joomla’s own admin list.
2.5.8 Target Size (Minimum), AA
Click targets at least 24×24 CSS pixels, or spaced far enough apart.
Tiny social icons and close buttons. The audit measured a 20×20 px remove icon in core forms.
3.2.6 Consistent Help, A
Help options (contact details, chat, FAQ link) stay in the same relative order on every page.
Contact links or chat widgets that move between templates and menu layouts.
3.3.7 Redundant Entry, A
Don’t make people type the same information twice in one process.
Checkout and booking forms that ask for the address again.
3.3.8 Accessible Authentication (Minimum), AA
No memory test or puzzle to log in unless there’s an alternative or help.
Login forms that block paste or password managers, and puzzle CAPTCHAs with no alternative.
The full WCAG 2.2 table and copy-paste template fixes are in our European Accessibility Act guide, so we won’t repeat them here.
What does Joomla core give you, and what must you fix yourself?
Joomla has made accessibility a priority since version 4. The Joomla Accessibility Project puts it carefully: Joomla “currently aims for WCAG 2.1 AA conformance since Joomla 4, but this has never been independently validated.” This table shows where core helps, where the 2026 audit found gaps in core itself, and what stays your job.
Area
What core gives you
Gaps the 2026 audit found in core
Your responsibility
Templates
Cassiopeia (site) and Atum (admin), both built with accessibility as a goal
No skip link in Cassiopeia by default; current-menu and focus indicators below 3:1 contrast; undefined focus styles in Atum
Third-party templates, page builders, child templates, overrides and any colours you change
Content editing
Alt-text fields with a decorative-image option; the jooa11y checker in the article editor
Media Manager not usable by keyboard (critical); editor can disappear while scrolling on small viewports (critical)
Real alt text, heading order, link text, captions and tagged PDFs in every article
Forms and login
Core login, registration and multi-factor authentication (MFA)
Calendar date picker not keyboard or screen-reader accessible; password rules not tied to the field; MFA QR code without alt text (critical)
Contact, booking and checkout extensions, CAPTCHAs and error messages
Interaction
Core Skip-To plugin (on for the administrator by default) and the “Additional Accessibility Features” visitor toolbar
Inaccessible tooltips; dialogs don’t return focus; sessions time out without warning
Menus, sliders, popups, cookie banners, chat widgets and maps
Admin screens
Atum accessibility settings for backend users
Extension list not usable by keyboard (critical); low-contrast checkboxes
Matters if staff with disabilities manage your site
A quick fix for the skip link: the core Skip-To plugin is enabled for the administrator by default and can also be switched on for the site. You can do that under System → Plugins, or add a “Skip to main content” link in a Cassiopeia child template.
What did the 2026 independent audit of Joomla find?
Open Source Matters commissioned an independent audit from Axess Lab as Milestone 1a of the Joomla Accessibility Project, which is funded through the Sovereign Tech Fund. Eric Eggert tested Joomla in July and August 2026 against WCAG 2.2 Level AA, and the audit report was released on 17 August 2026. The scope covered Atum, Cassiopeia, login and MFA, the Media Manager, the installer and update flows, backend list and edit views, frontend user forms, and configuration and permissions.
42 issues: 4 critical, 15 serious, 16 moderate and 7 minor, plus one best-practice suggestion.
Success criteria: 27 failed, 17 passed, 8 not applicable and 3 not tested.
The four critical issues: the Media Manager, the editor vanishing on small viewports, the extension list not working by keyboard, and an MFA QR code with no text alternative.
The auditor’s verdict: the number of findings is “better than average for a project like this”.
A separate audit against ATAG 2.0, the guidelines for authoring tools, found five issues. It matters if your editors have disabilities, because Joomla is the tool they use to create content. The Joomla Community Magazine summary covers both audits.
What happens next?Milestone 1b runs from 1 September to 31 October 2026 and is listed as in progress on the project milestones page. It covers a prioritised remediation backlog and quick-win fixes merged into Joomla core. The Joomla feature tracker also lists WCAG 2.2 AA compliance for Joomla 6.x as in planning. Joomla 6.2, released on 13 October 2026, is the latest version. Check each release’s notes for which audit fixes have shipped. Until a fix lands in the version you run, that gap is yours to work around.
What does the ADA require for websites?
The Americans with Disabilities Act covers state and local governments (Title II) and businesses open to the public (Title III). According to the Department of Justice, it has “consistently taken the position” that the ADA applies to web content since 1996. What changes between the two titles is how specific the technical rules are.
Title II: state and local government websites
The DOJ final rule was published in the Federal Register on 24 April 2024. It sets WCAG 2.1 Level AA as the technical standard for web content and mobile apps from state and local governments. That includes public schools, colleges and universities, libraries, courts, transit agencies, public hospitals and special districts. An Interim Final Rule published on 20 April 2026 extended the compliance dates:
Public entity
Compliance date
Total population of 50,000 or more
26 April 2027
Total population under 50,000
26 April 2028
Special district governments (any size)
26 April 2028
Vendors are covered. Content that a contractor builds or posts for a public entity must meet WCAG 2.1 AA. DOJ’s own example is a county parks page made by a local web design company. If your agency builds Joomla sites for cities, schools or libraries, your work is in scope.
Third-party tools the entity adds are covered too: calendars, maps, reservation systems and payment forms.
School districts use the population of their city or county, or a Census estimate for independent districts, to find their date.
The rule has limited exceptions. Each one has conditions, and none removes the duty to give a person with a disability an accessible version when they ask:
Archived content: created before the compliance date, kept only for reference, stored in an archive area and unchanged since.
Preexisting documents: PDFs, Word, presentation and spreadsheet files posted before the compliance date, unless people still use them to apply for or access a service.
Third-party posts: content posted by members of the public, not by the entity or its contractors.
Individualised, password-protected documents such as a resident’s water bill.
Preexisting social media posts made before the compliance date.
Title III: businesses open to the public
Title III requires businesses open to the public to give people with disabilities full and equal enjoyment of their goods and services, and DOJ applies that to websites. But DOJ guidance also says the Department “does not have a regulation setting out detailed standards”. Businesses have flexibility in how they comply, and DOJ points to WCAG and the Section 508 Standards as helpful guidance. The same guidance page lists DOJ website settlements with businesses including H&R Block, Peapod and Rite Aid.
In practice, WCAG is the benchmark commonly referenced in private ADA website lawsuits, demand letters and settlements. For a US business running Joomla, WCAG 2.1 AA is the minimum sensible target and WCAG 2.2 AA is the better one. Outcomes vary from case to case, so we don’t quote lawsuit counts here.
Section 508: federal agencies and their suppliers
Federal agencies follow Section 508 of the Rehabilitation Act. The Revised 508 Standards require electronic content to conform to WCAG 2.0 Level A and AA. A Joomla site built to WCAG 2.1 or 2.2 AA covers those 2.0 criteria as well.
Selling to the EU or UK too?
If you sell to consumers in the EU, the European Accessibility Act can apply wherever your business is based. Our European Accessibility Act guide covers who it applies to, EN 301 549 and the UK rules.
General information, not legal advice. Whether and how the ADA applies to your organisation is a question for a qualified attorney.
How do you audit and fix a Joomla site for WCAG 2.2 AA?
This is the process we use on Joomla sites for US owners and agencies. It works whether you do it in-house or hire help. The test steps mirror the screen-reader and browser pairs the Joomla Accessibility Project uses for core.
1. Inventory your page types
You don’t test 2,000 URLs. You test each type of page and each extension that renders something. List these: home page, category blog and list views, a typical article, contact and other forms, login and registration, search results, checkout or booking, an events calendar if you have one, embedded video and maps, and your most-downloaded PDFs. Note which template layout and which extension produces each one.
2. Run automated scans
Turn on jooa11y (System → Plugins → “System – Joomla Accessibility Checker”). It has been a core plugin since Joomla 4.1. Use the Accessibility Check button on your key articles. As the Joomla manual says, it identifies problems but doesn’t fix them.
Run WAVE and axe DevTools on every page type from step 1. Our free accessibility checker gives a quick second opinion.
Export or screenshot the results. They become your baseline.
3. Do a keyboard-only pass
Put the mouse away. Use Tab, Shift+Tab, Enter, Space, the arrow keys and Escape through the menu, search, forms, popups, the cookie banner and checkout. Check that focus is always visible, follows a logical order, never gets trapped, isn’t hidden under a sticky header (2.4.11), and returns to the trigger when a modal closes. Our keyboard navigation tester helps you record what you find.
4. Spot-check with a screen reader
Use NVDA with Chrome or Firefox on Windows and VoiceOver with Safari on macOS or iOS. Pull up the headings list and the landmarks. Tab through a form and listen: does every field have a label, and is every error announced? Do icon buttons have names? These are the problems scanners can’t judge.
5. Check contrast and target size
Check that normal text has at least 4.5:1 contrast, and that large text, icons, form borders and focus indicators have at least 3:1. Interactive targets should be at least 24×24 CSS pixels or well spaced. Use our free contrast checker for colours and the PDF accessibility checker for documents.
6. Map findings to WCAG and prioritise
Log every issue with its WCAG success criterion, the page type, its severity, and its source: template, extension, content or Joomla core. Fix blockers first, meaning anything that stops someone navigating, logging in, submitting a form or paying. Low-contrast footer text can wait a sprint; an inaccessible checkout can’t.
7. Fix at the source
Template: use a child template and layout overrides, so fixes survive template updates. Our European Accessibility Act guide has the skip-link, focus and contrast snippets.
Extensions: update first. Ask the vendor about accessibility, for example whether they publish a conformance report (often called a VPAT or ACR). Then patch the output with an override, or replace the extension.
Content: write real alt text, fix heading order, rewrite “click here” links, add captions and tag your PDFs.
Joomla core: keep current with Joomla 6.2 updates and work around known core gaps, such as enabling the Skip-To plugin on the site.
8. Publish an accessibility statement and a feedback route
Add an “Accessibility” page linked in the footer. It should say which standard you aim for (for example WCAG 2.2 AA), when you last tested, any known limitations, how to request content in another format, and how to report a problem by email or phone. DOJ guidance notes that a way to report accessibility problems helps site owners fix them. Don’t write “fully ADA compliant”; describe what you tested and what you’re doing.
9. Re-test after every update and keep a log
Accessibility breaks quietly. A template update, a new slider or a Joomla release can undo past fixes. Re-test the affected page types after each change, have editors run jooa11y before they publish, and keep a dated log of what you tested and fixed. If a complaint arrives, that log shows your good-faith work.
Which tools should you use to test a Joomla site?
Use automated tools to find the easy problems fast, then use people to find the rest:
Tool
Cost
Best for
Limits
jooa11y (Joomla Accessibility Checker)
Free, in core since Joomla 4.1
Article content: alt text, headings, link text, captions, PDF links
Checks content, not your whole template; finds problems, doesn’t fix them
WAVE (WebAIM)
Free browser extension
Visual markers on the page; good for learning
Automated checks only
axe DevTools (Deque)
Free extension, paid tiers
Developer-grade rule checks for each page type
Automated checks only
Lighthouse
Built into Chrome
A quick accessibility score next to performance and SEO
A subset of checks; a perfect score doesn’t mean the site is accessible
“A ‘clean’ report does not necessarily mean everything is accessible.” The US Department of Justice, in its web accessibility guidance, which recommends pairing automated checkers with a manual check.
You’ll see many different percentages quoted for how much automated tools catch. The estimates vary with the method, and we haven’t found a primary source we trust, so we don’t quote one. The practical rule holds either way: scan first, then test by hand.
Do overlays or a “Joomla ADA plugin” make your site compliant?
No. An overlay adds a script and a toolbar on top of your page. It doesn’t change the template, extension or content that actually fails. Regulators have acted on claims like these. In January 2025 the US Federal Trade Commission proposed an order requiring accessiBe to pay $1 million over claims that its accessWidget could make any website WCAG-compliant. The FTC approved the final order on 22 April 2025. It bars the company from claiming its automated products can make any website WCAG-compliant, or keep it compliant over time, unless it has evidence to support the claim. DOJ’s guidance makes the same general point: automated checkers and overlays “need to be used carefully”.
Visitor toolbars can still help some people with text size, spacing, contrast or a reading guide. Joomla core even ships one, the “Additional Accessibility Features” plugin. As the Joomla Community Magazine notes, it doesn’t solve any accessibility problem your site has. Treat a toolbar as a comfort feature on top of an accessible site, not as a fix.
So what is the best Joomla accessibility plugin?
It depends on the job, because each type of tool does a different one:
To find issues: jooa11y (free, in core), plus WAVE and axe.
To patch mechanical gaps: self-hosted helper plugins that fix the HTML your site sends. For example, our own Easy WCAG (we make it, so weigh that) adds missing lang, alt and iframe titles, labels icon links and form fields, adds a skip link and reports what still needs a person. It doesn’t replace an audit.
To give visitors preferences: a self-hosted toolbar, such as Joomla’s core plugin or our Easy Accessibility module. It’s useful for comfort, but it isn’t a compliance tool.
To avoid: anything that promises “instant ADA compliance” or a compliance certificate.
When should you bring in a Joomla accessibility team?
A small brochure site on the default template can often work through the checklist above in-house. It’s worth getting help when:
You’re a public entity, or a vendor to one, facing the April 2027 or April 2028 Title II date on a large site.
Your site uses a third-party template or page builder, or lots of extensions.
You run checkout, booking, membership or application forms, where one barrier blocks a whole task.
You have years of PDFs and media to triage.
You also need to upgrade to Joomla 6.2. Fixing accessibility during the upgrade avoids doing the template work twice.
Infyways has been around since 2010 and makes 125 Joomla extensions, so we know how templates and extensions render under the hood. Our Joomla development team audits against WCAG 2.2 AA (mapped to 2.1 AA for Title II), fixes templates and overrides, repairs or replaces extensions, cleans up content and PDFs, drafts your accessibility statement and re-tests after the fixes. We often pair this with performance optimisation, because clean, well-structured pages also tend to load faster. We don’t sell certificates or legal guarantees. We remove barriers and document the work.
No CMS is ADA compliant on its own. Joomla 5 and 6 aim for WCAG 2.1 AA in core and ship an accessible default template and a built-in checker. But your template, extensions and content decide whether your site meets WCAG, which is the benchmark ADA rules and settlements use.
Is Joomla WCAG 2.2 compliant?
Not fully yet. An independent WCAG 2.2 AA audit of Joomla core by Axess Lab, released on 17 August 2026, found 42 issues (4 critical) and 27 failed success criteria. The Joomla Accessibility Project is now turning them into a remediation plan and core fixes.
What WCAG level does the ADA require?
For state and local governments, the DOJ Title II rule requires WCAG 2.1 Level AA. For private businesses under Title III, DOJ has no technical regulation. It points to WCAG and Section 508 as guidance, and WCAG 2.1 or 2.2 AA is the commonly used benchmark.
When is the ADA Title II website deadline?
After DOJ’s Interim Final Rule of 20 April 2026, the deadline is 26 April 2027 for public entities with a population of 50,000 or more. It’s 26 April 2028 for smaller entities and all special district governments.
Is there a Joomla ADA or WCAG plugin that makes my site compliant?
No plugin can guarantee compliance. The built-in jooa11y checker finds content issues, and self-hosted helpers can patch some mechanical gaps such as missing alt text or labels. Templates, forms and content still need manual fixes and testing.
Do accessibility overlays work?
They can add visitor preferences, but they don’t fix your site’s underlying code. In April 2025 the FTC finalised an order requiring accessiBe to pay $1 million over claims that its widget could make any website WCAG-compliant.
How do I check my Joomla site’s accessibility?
Run jooa11y on your articles and WAVE or axe on each page type. Then test everything by keyboard and spot-check with NVDA or VoiceOver. Automated tools find only part of the issues, so the manual checks matter most.
Does the European Accessibility Act apply to my US Joomla site?
It can. If you sell covered services, such as online shopping, to consumers in the EU, the EAA can apply wherever you’re based. See our Joomla European Accessibility Act guide for details.
Disclaimer: This article is general information about US and international accessibility standards as of October 2026. It is not legal advice, and following it does not guarantee compliance with the ADA or any other law. Check your obligations with a qualified attorney.
A Joomla extension conflict is two (or more) extensions changing the same request, often by listening to the same plugin event, until the site misbehaves or PHP fatals. The last thing you installed is the first suspect. The reliable find is a binary search: disable third-party plugins in batches on a staging copy, then re-enable until the clash returns. Do not disable core plugins at random on production.
A conflict is not “the zip failed to install.” If the package never registered, use Joomla extension installed but not working. If the whole site is a 500, capture the log first: Which Joomla extension is causing a 500 error. This page is for the site that still runs, but SEF, login, cache, editor, or a component view breaks once two add-ons are enabled together.
Same event, two listeners, undefined order. The second plugin sees HTML or a routing state the first already changed.
What you will learn
How to tell a conflict from a single broken extension
Why “what did we install last” is the fastest start
How to read a PHP error as a file path under plugins/
How to disable third-party plugins in batches without taking core down
What “two plugins on the same event” looks like in practice
When to stop and use a maintained staging copy instead of live trial and error
PHP fatal naming a file in plugins/system/x and plugins/system/y
Both loaded, one fatals on the other’s result
Single extension 500
Admin works, site does not (or reverse)
client_id / site vs admin plugins
Template only
Conflicts cluster in system and content groups because those events run on almost every request: onAfterInitialise, onAfterRoute, onAfterRender, onContentPrepare, cache, and SEF.
Two SEF plugins, two “security / firewall” plugins, a page cache plugin plus a plugin that needs cookies, an editor-xtd button plus a content filter that strips the same tag: those are classic pairs.
Do not “fix” a conflict by editing the vendor’s PHP on production. The next update restores the clash. If you must change HTML a plugin prints, use a layout override when it has tmpl: Joomla plugin override. If you must change behaviour, disable one extension or replace it. Keep core files stock: Customize Joomla without editing core.
Step 1: Write down what changed last
Before you disable anything, record:
Last extension installed or updated (name, version, date).
Last Joomla or PHP change on the host.
Last time someone enabled a plugin that had been off.
Whether the failure is site, administrator, or both.
If the failure started in the same hour as a package, disable that package first (its plugins, then its modules, then the component). Many “conflicts” are one bad release fighting core, not two third parties. You still confirm by turning it off.
If nothing was installed, look at System → Manage → Extensions, sort by Date, and at host changelogs (PHP 8.2 to 8.3 is a common silent change).
Work on a staging copy when you can. Disabling plugins on a live shop during business hours is how you create a second incident. If you have no staging, take a full backup (files and database) before batch disables. Infyways can hold that process for you: Joomla support and maintenance.
Step 2: Turn the PHP error into a path
A conflict often announces the file.
On staging (or briefly on production if you must): System → Global Configuration → System set Debug System to Yes. Server set Error Reporting to Maximum. Save.
Reproduce once. Read the message. Turn Debug off and Error Reporting back to System Default when you finish. Do not leave Maximum on a public site.
If the administrator is already down, you cannot use that UI. Use the 500 article: configuration.php$debug and $error_reporting, plus the PHP error_log.
The path is the clue:
plugins/system/cache/… vs plugins/system/yourcdn/…
plugins/content/emailcloak/… vs a content plugin that already wrapped emails
plugins/behaviour/… plus a third-party system plugin that still calls removed class names
If PHP names one file only, start there. It may still be a conflict (that file fatals because another plugin changed state). If the stack lists two extension folders, you have the pair.
Empty error with a “wrong” page only: might not be PHP. Might be two plugins rewriting HTML. Batch disable still works.
Step 3: Disable third-party plugins in batches
Goal: prove the site works with only core, then add half the third-party plugins back, then half of that half. That is a binary search. It is faster than one-by-one on a site with forty plugins.
Rules:
Do this on staging first.
Do not disable Joomla core plugins you do not understand (Authentication, User, Behaviour, System – Language Filter on a multilingual site, System – SEF if you rely on it). If you disable Language Filter on a live multilingual site, you will create a worse outage than the conflict.
Prefer the administrator: System → Plugins. Filter Site vs Administrator if needed. Filter by author or by a search that excludes Joomla!.
Unpublish (disable) a batch of third-party system plugins first. Reload the broken page. If the bug is gone, the conflict is in that batch. Re-enable half. Repeat until one name remains.
If system plugins are not the cause, batch content plugins next, then other groups (user, authentication, extension, privacy, and so on).
A practical batching order:
Everything third-party in system that is not your payment or firewall must-keep list.
Third-party content plugins (filters, shortcodes, related items).
Third-party user / authentication if the bug is login.
Modules last. A module rarely conflicts with another module the way two system plugins do. It can still break a page if both output the same JS global. Unpublish the extras in System → Site Modules if the binary search on plugins did not land.
If administrator login dies after a disable, you went too far (often authentication or a behaviour plugin). Restore from backup or set #__extensions.enabled = 1 for that plugin in the database. The fatal-error manual describes that table. Do not guess core rows.
When one plugin is identified, leave it disabled and re-enable the rest. Confirm the site is healthy. Then enable the suspect alone on a clean plugin set. If it fails alone, it is a broken extension, not a pair. If it fails only with one other plugin, you have the conflict pair.
Step 4: Check two plugins on the same event
Once you have two names, confirm they share a hook.
You do not need to be a developer. Open each plugin’s main PHP file on staging (read only) and search for onAfterRender, onAfterRoute, onAfterInitialise, onContentPrepare, onContentAfterDisplay, or similar on* methods. If both implement the same function, they both run. Order is the Ordering column in System → Plugins.
What to try, in this order:
Change Ordering so the plugin that should see original HTML runs first (or last, depending on the job). Save. Test. Ordering is a real fix when one plugin must wrap output the other already built.
If both claim to be “the” SEF, cache, or security layer, you cannot order your way out. Keep one. Uninstall or leave the other disabled.
Look for a setting on one plugin: “don’t process admin,” “exclude component,” “don’t run on POST.” Use those before you write custom PHP.
Events for custom fields and content are documented in the content events manual. Two content plugins both rewriting onContentPrepare is how shortcodes disappear or how {field} output gets double-escaped.
Do not edit the vendor files to comment out a method. That is a core-style hack on an extension. Use disable, order, or a replacement.
Step 5: Components, modules, and “it only happens on one view”
If plugins are clean and com_example plus com_other fight:
Open each component’s menu item. Note query vars.
Disable one component’s modules and plugins (packages install all three). A “component conflict” is often its system plugin.
Test the view with a stock Cassiopeia style to rule out a template JS conflict. Template JS vs extension JS is still a conflict. Put scripts in user.js on a child if you own them: Add custom JavaScript to Joomla.
Page builders plus core com_content fields, two backup plugins running cron, two Google Analytics plugins injecting gtag twice: isolate by disable, not by stacking more extensions.
Cache, SEF, and language plugins (the usual trio)
If the “conflict” is wrong URLs, mixed languages, or a page that is stuck in time, check this trio before you batch forty content plugins:
System – SEF (core) plus a third-party SEF or router plugin. Keep one rewriter. Two of them is the most common routing conflict.
System – Page Cache (or a full-page cache extension) plus a plugin that varies output by user, cart, or language. Cache serves the first visitor’s HTML to the second. That looks like a random conflict. Exclude the component, or disable page cache on staging while you test.
System – Language Filter plus a third-party language or translate plugin. On a multilingual site, disable the extra translator first. Do not disable Language Filter on production as your first move.
A cookie or privacy plugin that strips scripts, plus a plugin that injects those scripts on onAfterRender, will clash until one of them has an allow list. Ordering can help. Two products that both claim to own the footer usually cannot.
When you finish a batch search, write the two names in a site runbook. The next admin who enables both because both were paid for will recreate the outage.
Step 6: After you know the pair
Keep a note: names, versions, event, whether order fixed it.
Check each vendor for a Joomla 5 / 6 build. An old Joomla 3 plugin on Joomla 5 is a conflict with core, not with your other add-on.
Uninstall the one you will not keep, or leave it disabled with a comment in your runbook so someone does not “helpfully” enable it.
Clear cache. Reload logged out.
Turn Debug off.
If the pair is required for business (payments plus a tax plugin) and order does not help, that is a development or vendor ticket, not more toggling. Maintenance retainers exist for that: Joomla support and maintenance.
Do not confuse a conflict with a template override that fatals only when a plugin injects extra HTML. If the stack names templates/ and plugins/, disable the plugin first on staging. If the page recovers, the override assumed markup the plugin changed. Diff the override against core and put the repaired copy in a child. That is still a conflict. The durable fix is a plugin you can update plus an override you own, not a patched vendor file.
Last change first. Then a PHP path if you have one. Then batch disable on staging. Then confirm the shared event.
Key takeaways
A conflict is two extensions on one request, often the same plugin event. Isolate with disables, not with core hacks.
Start with the last installed or updated package. Many clashes are one bad release.
A PHP error that names a file under plugins/ is a gift. Read the path before you guess.
Batch-disable third-party plugins on staging (binary search). Do not randomly disable core authentication or language filter on production.
When two plugins share onAfterRender or onContentPrepare, try Ordering, then keep only one SEF/cache/security layer.
Packages include plugins. Disable those before you uninstall a component you still need.
Restore Debug and Error Reporting when you finish. Maximum error output is for the hunt.
If you cannot take production down, copy the site and hunt there. That is cheaper than an hour of live outage.
Frequently asked questions
How do I find a Joomla extension conflict?
Reproduce the failure, note the last install, then disable third-party plugins in batches on staging until the failure stops. Re-enable half at a time until one plugin (or a pair) is left.
Should I disable all plugins including core?
No. Core authentication, user, and (on multilingual sites) language filter keep the site usable. Batch third-party system and content plugins first.
Two plugins listen to the same event. What then?
Change Ordering and test. If both try to own SEF, cache, or security, disable one. You cannot merge two full-page rewriters.
Why did this start after an update, not an install?
The update changed one listener’s HTML or PHP. The other plugin still expects the old output. Same conflict method: last changed extension first, then batches.
Can a module conflict with a plugin?
Yes, usually through JavaScript or through a plugin that rewrites module HTML on onAfterRender. Unpublish the module to test, then the plugin.
Is editing the plugin PHP a valid fix?
Not on production, and not if you want updates. Disable, order, override a tmpl if one exists, or replace the extension.
When should I use a maintenance team?
When you have no staging, when administrator login is at risk, or when two business-critical extensions fail together after you isolate the pair.
Updated 14 October 2026 · By Abhilash Sahoo, Infyways
To check whether your Joomla extensions are compatible with Joomla 6, install the free Migration Scanner from JoomlaX on a staging copy of your site, click Scan site, and read the Dashboard. It inventories every enabled third-party component, module, plugin and template, scans their PHP and XML files, and labels each extension Will not run, Needs review or Ready. For every problem it shows the file, the line number and the replacement code. The scan is read-only and never runs extension code.
In short: Migration Scanner is a free Joomla administrator component for Joomla 4.4, 5 and 6 (PHP 8.1+). It answers one question before you upgrade: which installed extensions will break on my target Joomla version, and where exactly?
Why do you need a Joomla 6 compatibility check?
Most Joomla upgrades do not fail because of Joomla core. They fail because of a third-party extension or template that still uses old Joomla 3-era code, such as JFactory, JText, JRequest or JHtml behaviours.
Joomla keeps many of these old names alive through its backward compatibility plugin (plg_behaviour_compat on Joomla 4/5, plg_behaviour_compat6 on Joomla 6, where the Classes Aliases option is off by default). Everything compat6 covers is scheduled for removal in Joomla 7. For the exact settings per version, see our Joomla backward compatibility plugin guide; for what changed in the release itself, see what’s new in Joomla 6.
So an extension that “works” today may only be working because a compatibility layer is propping it up. A compatibility check tells you which extensions are genuinely ready, which are leaning on the plugin, and which will not run at all.
What is the JoomlaX Migration Scanner?
Migration Scanner is a free, read-only Joomla administrator component that finds legacy PHP APIs and incomplete manifests before you move a site to Joomla 6. It is built and maintained by Infyways under the JoomlaX brand.
Details
Price
Free (no checkout)
Installs on
Joomla 4.4, 5.x and 6.x
PHP
8.1 or later
Database
MySQL or MariaDB
What it reads
PHP and XML files of enabled, non-core components, modules, plugins and templates
Site owners planning a Joomla 3, 4 or 5 to Joomla 6 upgrade who want to know what will break before they start.
Agencies that need a printable, shareable report of every blocker on a client site.
Developers who maintain custom or abandoned extensions and need a file-and-line list of what to rewrite.
What does Migration Scanner detect?
The scanner token-scans PHP and checks XML manifests for a namespace. Each finding is grouped by API, given a severity, and tagged with the compatibility layer it depends on.
Status for each extension
Status
Meaning
Will not run
Uses APIs the compatibility plugin cannot save. Must be rewritten for the target version
Needs review
Still depends on compat6 aliases or similar layers
Ready
Nothing blocking for the chosen target version
Finding types (chips)
Needs aliases: old class names such as JText or JFactory that only work while Classes Aliases are enabled in compat6.
Needs legacy classes: code that depends on legacy classes the compatibility plugin still ships.
Needs asset stubs: references to removed assets that the plugin stubs out.
Will not run: calls the compatibility plugin cannot rescue.
Severity
Findings are ranked Critical, High, Medium and Low, so you fix what will stop the site first.
Grouped, not duplicated
If JText appears 48 times in one component, you see one group (“JText · Needs compat6 aliases, 48 times”) instead of 48 separate lines. You fix a pattern, not a pile of duplicates. Expand a group to see why it matched and what to put instead.
Unzip it on your computer. Inside you will find pkg_jxmscanner_*.zip (the file you install) and ReadMe.txt.
In the Joomla administrator, go to System > Install > Extensions and upload pkg_jxmscanner_*.zip.
Open Components > Migration Scanner to confirm the Dashboard loads.
Clear the cache: System > Maintenance > Clear Cache.
You need a Super User or administrator account. You do not need jQuery, a CLI or any extra plugins. Updates use the same steps, and previous scan results stay in the database.
Tip: Do not install the outer _UNZIP file in Joomla. Install the inner pkg_jxmscanner_*.zip.
Still on Joomla 3? How to use the Migration Scanner
The Migration Scanner extension needs Joomla 4.4 or later, so it cannot be installed on a Joomla 3 site. You have two options: scan each extension or template ZIP now with our free online Joomla Migration Scanner, or upgrade a staging copy to Joomla 4.4 and install the extension there. Joomla’s official path is 3.10 → 4.4 → 5.4 → 6; you cannot skip Joomla 4.
Option A: scan ZIP packages online (no upgrade needed)
Collect the installation ZIPs of your third-party extensions and template (from the developer, or zip the folders from your site).
Run it on a staging copy of your site. The scan is read-only, but a large site can take several minutes and is easier to review away from production.
Open Components > Migration Scanner.
Read the host banner. It tells you whether plg_behaviour_compat or plg_behaviour_compat6 is enabled, and whether Classes Aliases, Legacy Classes and Removed asset stubs are on.
(Optional) Open Configuration and set the Target Joomla version and Files per step.
Click Scan site and wait until the live status pill shows Idle.
Use the Dashboard plan, then open an extension marked Will not run.
Configuration: target version and files per step
Target Joomla version:Auto targets Joomla 6. Pick 4 or 5 if you are staging an upgrade to that version.
Files per step: how many files each scan step reads (default shown: 40). Lower it if the scan hits PHP max_execution_time on cheap hosting.
Permissions tab: Super Users can set component permissions.
Save, then run a new scan so the counts match the new target.
How do I read the results?
1. Dashboard: the plan
The Dashboard shows four site-wide counts: All extensions, Will not run, Needs review and Ready. Do this first lists the blockers, and Needs work first is a short table of the worst extensions. From the header you can Scan site, Pause, Export JSON and open the Site report.
2. Extensions: the inventory, worst first
Components > Migration Scanner > Extensions ranks every third-party component, module, plugin and template from worst to best. Filter by status or type, search by name or element (for example com_example), and open a row for its findings. Joomla core never appears here.
3. Findings: file, line and replacement
Open one extension to see All APIs, the alias, legacy and asset-stub layers, and the Will not run items. Each finding names the file path, the line and the replacement. After you edit files, click Scan this extension to re-check just that one; you don’t need to rescan the whole site.
4. Share it
Export JSON: a machine-readable export that includes bc_layer, bc_param and removed_in for each finding.
Site report: a printable view for agencies, developers and clients.
How do I fix the issues it finds?
Work from the top of the Dashboard plan:
Update first. Check whether the developer has released a Joomla 5/6 version. Updating often clears dozens of findings at once. Rescan afterwards.
Replace abandoned extensions. If the developer has stopped updating the extension and it is marked Will not run, look for a maintained alternative.
Fix “Needs aliases” items. Replace old names with namespaced classes, for example JText with Joomla\CMS\Language\Text and JFactory::getApplication() with Joomla\CMS\Factory::getApplication(). Our migration reference groups show the before/after code for each API.
Migration Scanner vs Joomla’s pre-update check vs manual checks
Joomla’s own pre-update check (System > Update > Joomla, with the update channel set to the next major version) checks required settings. For a Joomla 5 to 6 update it requires the old compatibility plugin to be disabled and Backward Compatibility 6 to be enabled. Its Extensions list relies on what each developer declares, so treat it as a high-level indicator, not proof that the code works.
Joomla pre-update check
Manual check
Migration Scanner
Looks at extension code
No (relies on developer update data)
Only if you read the code yourself
Yes: PHP tokens and XML manifests
File and line of each problem
No
Slow and error-prone
Yes, with replacement
Shows reliance on compat6 aliases / legacy classes
No
Hard to tell
Yes, per finding
Covers templates
Partly
Yes
Yes (enabled non-core templates)
Site-wide ranked plan
No
No
Yes, worst first
Shareable report
No
Your own notes
JSON + printable report
Cost
Built in
Your time
Free
They work best together: use Migration Scanner to find the code problems, fix them, then run Joomla’s pre-update check before the actual update.
Whole site or single ZIP: which scanner should I use?
We also run a browser-based Joomla Migration Scanner that checks one package. You drop a single extension or template ZIP into it, and it is useful before you install anything or when you only have the package. The JoomlaX extension scans the installed site: every enabled third-party extension at once, with a Dashboard plan and per-extension rescans. Use the online tool for one package, and the extension for a whole site.
DIY or hire help?
Do it yourself if the scan shows mostly Ready or Needs review extensions that have updates available, and you are comfortable editing PHP on staging.
Get help if you have Will not run extensions that are custom-built or abandoned, a Joomla 3 template, or no developer time. Migration Scanner has a Paid support tab for this. It is optional, and the scanner stays free.
Open Components > Migration Scanner > Paid support, or click Ask for paid support on the Dashboard or an extension report.
Name the extension and your target Joomla version.
Infyways quotes a rewrite. You only pay if you want the fix.
Scan never finishes: lower Files per step, check PHP max_execution_time on staging, and start again.
Old results showing: the Dashboard uses the newest scan. Run Scan site again after installing or updating extensions.
An extension is missing: only enabled third-party extensions are inventoried. Core and disabled items are skipped.
JavaScript files not listed: this release reads PHP and XML only.
Menu still says Preferences: clear the cache and open Configuration from the component submenu or the cog.
If a result does not match what you see in the files, open a ticket at support.joomlax.com. Include your Joomla and PHP versions, the extension element, and a JSON export or a screenshot of the finding.
Frequently asked questions
How do I check if a Joomla extension is compatible with Joomla 6?
Install the free Migration Scanner on a staging copy, leave the target on Auto (Joomla 6) and click Scan site. Each enabled third-party extension is marked Will not run, Needs review or Ready, with file-and-line findings. Also check the developer’s site for a Joomla 6 release.
Is Migration Scanner free?
Yes. The scanner is free to download and use. Paid support is optional and only applies if you want Infyways to rewrite an extension.
Which Joomla versions does it support?
It installs on Joomla 4.4, 5 and 6 and needs PHP 8.1 or later. You can target Joomla 4, 5 or 6 in Configuration.
Can I use the Migration Scanner on Joomla 3?
Not the extension: it installs on Joomla 4.4 or later. On a Joomla 3 site, scan each extension or template ZIP with our free online Joomla Migration Scanner, or upgrade a staging copy to Joomla 4.4 and install the extension there.
Can I upgrade from Joomla 3 straight to Joomla 6?
No. Joomla’s official path is 3.10 → 4.4 → 5.4 → 6. Each major upgrade requires the latest release of the previous version, so you cannot skip Joomla 4 or 5. Do every step on a staging copy first.
How do I check Joomla 3 extensions for Joomla 6 compatibility?
Upload each extension or template ZIP to the free online Joomla Migration Scanner, which reads Joomla 3 code. For a site-wide check, upgrade a staging copy to Joomla 4.4, install the Migration Scanner extension, and set the target to Joomla 6.
Does it change or break my extensions?
No. The scan is read-only. It does not execute extension PHP or run extension SQL, and it does not need write access to extension files.
Should I run it on a live site?
Run it on a staging copy. It is safe to run, but a large site can take several minutes, and the results are easier to review off production.
What files does it scan?
PHP and XML in enabled, non-core components, modules, plugins and templates. Joomla core, disabled extensions, JavaScript, CSS and SQL files are not scanned in this release.
What does “Needs compat6 aliases” mean?
The extension uses old class names (such as JText or JFactory) that only resolve while the Behaviour – Backward Compatibility 6 plugin has Classes Aliases turned on. It may work today, but compat6 is scheduled for removal in Joomla 7, so the code should be updated.
Joomla custom fields are not showing when a display gate is closed: Automatic Display is off or pointed at a slot the view never renders, the field is unpublished or not assigned to the article’s category, Access hides it, an override never prints the fields block, or cache is serving a page from before the field existed. Values can sit in the article editor and still never reach the public HTML. This page is troubleshooting only. The feature how-to is Joomla custom fields.
If you have not created the field yet, stop and use that how-to. If the Fields tab has a value and the frontend does not, stay here.
Admin can show a value while the public view never fires After Title, After Display, or your override. Treat display as a separate pipeline.
What you will learn
How to prove the value exists before you touch templates
What After Title, Before Display Content, After Display Content, and Do not automatically display actually inject
Why Assigned Categories All skips Uncategorised
How unpublished fields, ACL, and Display When Read-Only hide output
How article context vs category context sends you to the wrong Fields list
How a layout override or CSS can remove fields that Joomla did render
Why cache makes a fixed field look broken for hours
Category assignment, unpublished field, wrong context (Category vs Article), plugin off
Automatic Display
Value on the form, missing on the public article
Automatic Display, ACL, override, cache
“Joomla deleted the field”
Shows on the article, missing on the blog
Blog layouts often do not run the same display events the same way
Category assignment alone
Shows for Super Users, not for guests
Field Access or Display When Read-Only
Template chrome
Shows in HTML, not on screen
CSS, or label hidden and value empty-looking
Unpublished
Do not start in html/com_content/article/default.php. Start in Content → Fields.
Step 1: Confirm the value and the plugins
Content → Articles. Open the article. Open the field group tab (or Fields). Confirm the value is saved. If the input is missing in admin, this is assignment or context, not frontend display. Jump to Step 3 and Step 5.
System → Plugins. Search Fields. System – Fields must be enabled. Field type plugins (Fields - Text, Fields - Calendar, and the type you used) must be enabled. If you disable Fields - Media, media fields stop.
Content → Articles → Options → Integration. Custom Fields must be enabled for articles. Contacts and Users have their own Options.
If editors cannot type a value, that can be Edit Custom Field Value (core.edit.value) inherited as Not Allowed. Grant it on Content → Articles → Options → Permissions for the right group, or on the field. That is an admin ACL issue. Super Users still see values. Guests never will if Access on the field is Special.
Step 2: Set Automatic Display (After Title, After Display, or none)
On Content → Fields, open the field. Find Automatic Display:
Setting
Event
Where it usually appears
After Title
onContentAfterTitle
Under the title, before intro
Before Display Content
onContentBeforeDisplay
Above the body
After Display Content
onContentAfterDisplay
Below the body
Do not automatically display
none of the above
Nowhere, until {field ID} or an override prints it
Do not automatically display is the number one “not showing” after a careful setup. It is also the correct choice when you print fields in a child template layout. If you expected automatic output and left this on, change it to After Title or After Display Content, save, clear cache.
A whole group renders as one block in field order. If one field in the group is unpublished, the others can still show.
{field 12} in the article body needs the field id, not the name. Wrong id prints nothing useful. The Content – Fields plugin (or the editor Field button) inserts the syntax. If you type {field price} Joomla will not guess.
Blog (category) views and some third-party layouts do not call the same events, or they call them in a list context where you chose not to show fields. If the single article is fine and the blog is empty, Automatic Display is working. The blog layout is not a full article view. Use an override on html/com_content/category/ or accept fields only on the article.
Step 3: Fix category assignment (All does not mean Uncategorised)
The docs are explicit: the default All for Assigned Categories does not include Uncategorised.
If the article is in Uncategorised, the field can be absent from the editor and from the frontend. Assign Uncategorised explicitly, or move the article into a category you did tick.
Other assignment misses:
You ticked “News” but the article is in “News / 2026” as a child. Child categories are not automatic. Tick the child, or tick every category that should show the field.
You assigned the field to one category, then moved the article. The value may still exist in the database. The form and display rules follow the current category.
New articles: the Fields tab stays empty until a category is chosen. That is normal. Joomla waits so it can apply assignment.
After a K2-style migration, Uncategorised is common. The how-to covers the happy path: Joomla custom fields.
Step 4: Unpublished, Access, and read-only display
On the field:
Status must be Published. Unpublished fields are hidden in the editor for normal users and do not render on the site. Archived is the same idea with a different filter in Fields.
Access (Public, Guest, Registered, Special) applies to viewing the value on the frontend. A field set to Registered will not show to a guest. That is not a template bug.
Display When Read-Only: if the visitor cannot access the value, Yes still shows it, No hides it. Inherit follows the parent. A guest hitting a Registered field with Display When Read-Only = No sees nothing.
Language on the field: same trap as modules. A field set to French will not attach to an English article the way you expect.
ACL on the article can also stop the whole page. If the article is not viewable, fields are a side issue. Test logged out in a private window.
Step 5: Article fields vs category fields vs contacts
Content → Fields has a context switch: Article, Category, Contact, User (wording depends on what is installed).
If you created the field in Category context, it lives on the category edit form, not on the article. The article page will not print it as an article field. You will hunt Automatic Display forever.
If you created it under Contacts, articles will never show it.
Open Fields, set the filter to Article, and confirm your field is in that list. Title collisions across contexts are possible. Use the id in the URL when you edit.
Step 6: Overrides and CSS that hide fields
Automatic Display injects HTML when com_content (or contact) dispatches those content events in the view. A custom article layout that never triggers them will never print automatic fields.
Typical override failures:
html/com_content/article/default.php copied from an old template or a page builder, then stripped to $this->item->text only. Events never run. Fields vanish even with After Title set.
A html/layouts/joomla/content/ override that removed the after-title output.
A html/layouts/com_fields/field/render.php (or field render) override that returns empty, or wraps output in a class your CSS sets to display: none.
Alternative layout on the article (a different default_foo.php) that you never updated for fields.
Fix path: put overrides in a child, not in Cassiopeia core. Customize Joomla without editing core. If the field type uses a plugin tmpl, plugin overrides apply. Diff your default.php against the core file in components/com_content/tmpl/article/default.php. If core still calls the events and your copy does not, restore those calls.
CSS: inspect the public page. Classes like field-entry, field-label, field-value (exact names depend on layout) may be in the HTML. If they are, Joomla showed the field. Your user.css or the template hid it. If they are not in the HTML, you are still on Steps 2 to 5, not CSS.
Empty values: Automatic Display typically prints nothing useful when the value is empty. A required field that was never saved on old articles will look like “not showing.” Open the article and save a value.
Step 7: Cache, and then a frontend proof
After every field or override change:
System → Maintenance → Clear Cache.
If System – Page Cache is enabled, clear that too, or disable it on staging while you test.
CDN / host cache: purge the article URL.
Hard-refresh the public article logged out.
Joomla can cache the article HTML from before Automatic Display was set. You will swear the setting does nothing. The cached page is the old page.
Conservative caching of modules does not usually store article field HTML, but page cache does.
If the editor has no input, fix assignment and context. If the editor has a value, fix Automatic Display, Access, override, then cache.
Label hidden, empty value, and unpublished groups
Automatic Display can “work” and still look like a blank article.
Show Label is off and the value is a short code or a boolean that CSS does not style. Inspect the HTML. If a field-value (or the layout’s equivalent) is there, the field showed. You are in CSS or design, not in Fields.
The article never saved a value. Old articles created before the field existed stay empty until you open and save them. A default on the field applies to new items more reliably than to a thousand legacy rows.
Field groups have their own published state. An unpublished group can hide the tab in the editor, which looks like the field “vanished.” Publish the group, then the field.
Media and calendar fields fail in a specific way: the value is a path or a date Joomla cannot render in that layout. Open the article, confirm the media picker still points at a file that exists. After a migration, broken paths are common. That is data, not Automatic Display.
If you use {field ID} and the id is from a different context (you copied the id from a contact field onto an article), the shortcode will not fill. Use the Article fields list id.
Blog vs article, and third-party views
Single article (com_content article view) is where After Title / After Display are designed to run.
Category blog, featured, and tag views may show intro text only. Fields will not appear in the list unless the layout prints them. That is expected. Do not “fix” Automatic Display for a blog card. Override the blog item layout in a child, or keep fields on the full article.
Third-party components that are not com_content do not gain article fields by magic. They need their own field context or their own templating. A directory extension is not “Joomla custom fields not showing.” It is a different component.
Key takeaways
Troubleshooting starts in Content → Fields and the article form, not in random PHP.
Do not automatically display means the public page stays empty unless you use {field ID} or an override.
After Title and After Display Content only work in views that fire those content events.
Assigned Categories All skips Uncategorised. Tick it or move the article.
Unpublished fields, non-Public Access, and Display When Read-Only hide frontend output on purpose.
A field created in Category or Contact context will never show as an article field.
Article default.php overrides that drop content events remove automatic fields. Keep overrides in a child and diff against core.
Clear page cache after you change display. Old HTML is the most convincing fake bug.
Why are my Joomla custom fields not showing on the article?
Automatic Display is often Do not automatically display, the article category is not assigned (Uncategorised is the usual miss), Access is not Public, or an article override never fires the content events. Confirm the value in the editor first.
What is the difference between After Title and After Display?
After Title injects on onContentAfterTitle (under the title). After Display Content injects on onContentAfterDisplay (after the body). Before Display Content sits above the body. None of these run if you choose Do not automatically display.
Why does All categories not include Uncategorised?
That is core behaviour, documented on the custom fields parameters page. Assign Uncategorised explicitly or move the article.
Do custom fields show on the category blog?
Not unless that layout prints them. Automatic Display is built around item views that dispatch the content events. Use a category override if list cards must show a field.
Can an unpublished field still hold data?
The value can remain in the database. Unpublished means the field is hidden from normal editing and from frontend display. Publish it to use it again.
How do I show a field only in an override?
Set Automatic Display to Do not automatically display, then print the field in a child template layout. If you leave After Title on, you will get automatic output plus your override.
Could cache hide a field I just added?
Yes. Page cache and CDNs store the article HTML. Clear Joomla cache and the URL at the edge, then test logged out.