• Resolved Nicolas Cuny

    (@nicolas-cuny)


    Hello,

    I’ve traced a serious, data-losing bug to the REST API Optimizer that Burst installs as a must-use plugin (wp-content/mu-plugins/burst_rest_api_optimizer.php). Under the right conditions it silently deactivates most of the site’s plugins in the database.

    Root cause

    The mu-plugin filters the persisted option active_plugins:

    add_filter( 'option_active_plugins', 'burst_exclude_plugins_for_rest_api' );

    During a burst/v1/* REST request (for example burst/v1/do_action/chat_status), this makes every get_option(‘active_plugins’) call return a reduced list. Because active_plugins is a persisted option, if any active plugin writes it during that request — typically via deactivate_plugins() — it reads the filtered (truncated) list and writes it back with update_option(‘active_plugins’, …), persisting the truncated list to the database. The site’s other plugins are now deactivated.

    Concrete trigger

    Plugins that self-deactivate when a dependency looks missing are a perfect trigger. With WP All Import Pro and its ACF Add-On (wpai-acf-add-on) active, the filter hides WP All Import from active_plugins during the REST request, so the add-on concludes its dependency is missing and calls deactivate_plugins() during load (in wpai-acf-add-on.php). That write persists the truncated list. csv-xml-import-for-acf does the same in its plugin.php.

    Steps to reproduce

    1. Active plugins: Burst Statistics (with the REST API Optimizer mu-plugin), WP All Import Pro, and WP All Import ACF Add-On (wpai-acf-add-on).
    2. Cause a filtered Burst REST request to fire (e.g. open the Burst dashboard, which polls do_action/chat_status).
    3. The ACF add-on self-deactivates (it no longer “sees” WP All Import) and writes the truncated active_plugins, leaving the site with only a handful of active plugins.

    Evidence

    I added a temporary hook on update_option_active_plugins to log a backtrace whenever the list shrank. Captured line (verbatim):

    active_plugins 6->5 ctx=WEB uri=/wp-json/burst/v1/do_action/chat_status removed=wpai-acf-add-onstack: update_option << deactivate_plugins (wpai-acf-add-on.php) << wp-settings.php (plugin loading)

    Why it’s serious

    It is silent: the active_plugins option is overwritten, the site loses most of its functionality, and it recurs whenever the conditions coincide. It is hard to diagnose because the trigger (an admin-side Burst REST request) is unrelated to the plugins that disappear.

    Suggested direction

    Avoid filtering the persisted option active_plugins. Possible approaches: guard writes during the optimized request via pre_update_option_active_plugins (return the previous value), restore the full list before any write, or skip plugin loading through a mechanism that does not change the value seen by update_option().

    Environment: Burst Statistics 3.5.1, WordPress 6.9.4 (also reproduced on 6.8.3), PHP 8.3.

    Happy to provide more detail or test a patch. Thanks for the great plugin.

Viewing 2 replies - 1 through 2 (of 2 total)
  • Plugin Author Rogier Lankhorst

    (@rogierlankhorst)

    @nicolas-cuny thanks for your detailed report, that is very helpful. We will investigate and create a patch for the issue!

    Plugin Author Rogier Lankhorst

    (@rogierlankhorst)

    @nicolas-cuny After investigating the issue, we found that the cause is that the rest optimizer, which for performance reasons does not load all plugins, but requires some plugins (like the AI plugin) to be loaded, has too wide a match for the ai/ai.php plugin: it matches on “ai” only, which also matches on wpai-acf-add-on. As a result, it loads this plugin, but not the one it is dependent on, resulting in the issue you experienced. We will fix it in the next release.

Viewing 2 replies - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.