WP Manifestindependent plugin directory
manifest / utilities / wordpress-mu-loader

WP Plugin MU Loader WP Registry grade A-. Low-severity findings · 1 findingWP RegistryLow-severity findings · 1 findingOpen the reportA-

Loads regular plugins from the plugins directory as must-use plugins, enforcing their activity while maintaining the typical update flow.

★ 3stars
1.2.2latest · 4mo ago

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/thefrosty/wordpress-mu-loader/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

Installation

composer require thefrosty/wordpress-mu-loader:^1.1

Loads regular plugins from the plugins' directory as "must-use plugins", enforcing their activity while maintaining the typical update flow. This file will take care of all necessary logic, including preventing activation/deactivation/deletion of those plugins as regular plugins.

Benefits

  • Enforce plugins to be active throughout the entire installation.
  • Continue receiving automated update notifications.
  • Be able to comfortably update those plugins from the WordPress dashboard.
  • The plugin activation, deactivation, and uninstallation routines are executed as usual.

Requirements

  • WordPress >= 6.3
  • PHP >= 8.0

Usage

  • You can then pass basenames of the plugins you would like to load as MU plugins to the constructor call in the wp_plugin_mu_loader() function, as an array.
  • A plugin basename consists of the plugin directory name, a trailing slash, and the plugin main file name, for example wordpress-seo/wp-seo.php, jetpack/jetpack.php, or woocommerce/woocommerce.php.
  • Alternatively, if you don't want to tweak the code of the function itself, you can also access the loader from the outside: Retrieve the instance via wp_plugin_mu_loader() and then call its load_plugin() method, passing a single plugin basename string to it.

Example

wp_plugin_mu_loader()->loadPlugin( 'custom-login/custom-login.php' );

OR, create a git managed mu-plugin:

<?php declare(strict_types=1);
/**
 * @wordpress-muplugin
 * Plugin Name: WordPress Plugins as Must-use
 * Description: Require regular WordPress plugins as "must-use" plugins.
 * Version: 1.0.0
 * Author: Austin Passy
 * Author URI: https://github.com/thefrosty
 */

namespace TheFrosty;

use InvalidArgumentException;
use RuntimeException;
use function add_action;
use function array_filter;
use function array_walk;
use function file_exists;
use function function_exists;
use function wp_plugin_mu_loader;
use const WPMU_PLUGIN_DIR;

/**
 * Returns an array of basename formatted plugins to set as "must-use".
 * @return array
 */
function getRequiredPlugins(): array
{
    // Add plugins to the array here...
    return array_filter([
        'disable-emojis/disable-emojis.php',
        'soil/soil.php',
        'custom-login/custom-login.php',
        'wp-login-locker/wp-login-locker.php',
    ]);
}

add_action('muplugins_loaded', static function (): void {
    if (
        !function_exists('wp_plugin_mu_loader') &&
        // You only need the file_exists/require if not using autoloading...
        file_exists(WPMU_PLUGIN_DIR . '/wordpress-mu-loader/wp-plugin-mu-loader.php')
    ) {
        require_once WPMU_PLUGIN_DIR . '/wordpress-mu-loader/wp-plugin-mu-loader.php';
    }
    $loader = wp_plugin_mu_loader()
    $plugins = getRequiredPlugins();
    array_walk($plugins, static function (string $plugin_basename) use ($loader): void {
        try {
            $loader->loadPlugin($plugin_basename);
        } catch (InvalidArgumentException|RuntimeException $exception) {
            // Log something here?
        }
    });
});

Releases

6 releases.

Tag
Published
1.2.2 latest
Jun 9, 2026 4mo ago
Dec 18, 2025 10mo ago
Dec 14, 2025 10mo ago
Dec 6, 2024 1 year ago
Jan 27, 2023 3 years ago
Jul 4, 2022 4 years ago

These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.

A- grade

Security

WP Plugin MU Loader 1.2.2 · audited by WP Registry

Low-severity findings only.

1 low
Audited release
1.2.2
Findings
1
Worst severity
low
Content hash
d8782b4e3def15db03136ed8…

Findings

  • low MU-loader deactivate AJAX registered for nopriv without capability check

    unnecessary_attack_surface

    wp_ajax_nopriv_wp_plugin_mu_loader_deactivate shares ajaxCallback which only check_ajax_referer then runs plugin deactivation hooks. Nonces are created server-side, but nopriv + missing capability is unnecessary attack surface.

    src/WpPluginMuLoader.php:147-148,364-378

    Recommendation

    Remove nopriv registration; require manage_options in ajaxCallback.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.