Must-use plugins are a pretty niche topic. These are PHP files placed in the /wp-content/mu-plugins/ directory. Some characteristics and differences from normal plugins are:
- They are loaded before normal plugins (in alphabetical order).
- They don’t require any header comments.
- They are not displayed on the plugins page (only in a separate ‘Must-Use’ tab).
- They can’t be added via the admin panel (only manually, e.g., using FTP or SSH).
- They can’t be updated via the admin panel.
- They can’t be disabled in the admin panel (you’d have to delete the file to disable it).
- WordPress only looks for them in the /wp-content/mu-plugins/ directory, not in subdirectories.
Great, but why? Why do must-use plugins even exist? mu-plugins are great at ensuring that functionality critical to the site is never disabled. Imagine you’re making a website for a client and the website requires a custom post type. If you added it in a normal plugin and the website owner disabled it by accident, the entire site would crash. That’s a good reason to make it a must-use plugin.
Some plugins and themes also add their own mu-plugins. This is a rather controversial topic. Many of them have good reasons, often stemming from the fact that must-use plugins are loaded before normal plugins. That being said, it can be perceived as a breach of contract. When you install a normal plugin, you expect it to be a normal plugin, and not add persistent code that you can’t even delete from the dashboard.
Note that, because WordPress doesn’t search for mu-plugins in subdirectories, it’s often the best practice to make the actual PHP file just a simple loader responsible for requiring appropriate files. These can be files in a subdirectory of the mu-plugins folder, or more commonly with public plugins, files inside the /wp-content/plugins/the-plugin-folder/ directory.
Do you see how the previous example introduces persistence? The files loaded by the plugin’s mu-plugin code will be loaded even if the plugin is deactivated. It’s therefore the plugin’s responsibility to manage its must-use plugin, potentially removing it on the deactivation hook and updating it if needed.
Because most website owners and developers do not even know that mu-plugins exist, they are an attractive attack vector for hackers. Hackers have been known for putting malicious code in the mu-plugins directory to achieve persistence. Most people, even if they know they’ve been hacked, don’t know to check this directory for installed plugins, making them oblivious to the running malicious code.