I have ended up modifying function function pkg_call_plugins from
/etc/inc/pfsense-utils.inc
During XMLRPC config merges the core calls pkg_call_plugins("plugin_xmlrpc_recv", $pkg_sections). In stock code this invokes every installed package that registers a plugin_xmlrpc_recv* handler, regardless of whether that package’s own config is present in the incoming payload. That means unrelated plugins (e.g., pfBlockerNG on the secondary) can run on every merge and interfere with sync.
I modified pkg_call_plugins() in /etc/inc/pfsense-utils.inc to add one small guard:
For plugin_xmlrpc_recv* calls only, call a package’s handler iff the XMLRPC payload contains installedpackages/<pkgname>* keys for that package.
All other plugin types (send, normal hooks, etc.) are untouched.
In other words: only the packages whose config is actually being synced get their recv-hook called. This is just a workaround. Please don’t judge me too harshly.
function pkg_call_plugins($plugin_type, $plugin_params) {
$results = array();
$is_recv = (strncmp($plugin_type, 'plugin_xmlrpc_recv', 19) === 0);
foreach ((array)config_get_path('installedpackages/package', []) as $package) {
$items = (array)array_get_path($package, 'plugins/item', []);
if (empty($items)) {
continue;
}
// Derive package code name from configuration file (e.g. "pfblockerng.xml" -> "pfblockerng")
$cfg = $package['configurationfile'] ?? '';
$pkgname = $cfg ? substr(reverse_strrchr($cfg, '.'), 0, -1) : ($package['name'] ?? '');
foreach ($items as $plugin) {
if (!is_array($plugin) || (($plugin['type'] ?? '') !== $plugin_type)) {
continue;
}
// Minimal guard: on XMLRPC receive, only call the plugin if payload has installedpackages/<pkgname>*
if ($is_recv) {
$ip = $plugin_params['installedpackages'] ?? null;
$has_match = false;
if (is_array($ip)) {
foreach ($ip as $k => $_) {
if (strncmp($k, $pkgname, strlen($pkgname)) === 0) {
$has_match = true;
break;
}
}
}
if (!$has_match) {
continue;
}
}
$inc = $package['include_file'] ?? '';
if (!$inc || !file_exists($inc)) {
continue;
}
require_once($inc);
$fn = $pkgname . '_' . $plugin_type;
if (function_exists($fn)) {
$results[$pkgname] = call_user_func($fn, $plugin_params);
}
}
}
return $results;
}