REST API Optimizer can deactivate all active plugins
-
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
- 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).
- Cause a filtered Burst REST request to fire (e.g. open the Burst dashboard, which polls do_action/chat_status).
- 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.
You must be logged in to reply to this topic.