Files
argus-wp-defence/includes/class-argus-ajax-inventory.php
T
root df0f2fccb8 ARGUS WordPress Defence 1.0.0 — first production release
Automatic WordPress security: local firewall, malware and file-integrity
scanning, vulnerability protection, quarantine, scheduled backups, an
optional page cache, and automatic global threat intelligence.

See README.md for installation, update, and uninstall instructions.
2026-08-09 13:40:16 +00:00

70 lines
2.4 KiB
PHP

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Argus_AJAX_Inventory {
public static function snapshot() {
global $wp_filter;
if ( empty( $wp_filter ) ) {
return array();
}
$nopriv_actions = array();
foreach ( $wp_filter as $hook_name => $hook_obj ) {
if ( 0 !== strpos( (string) $hook_name, 'wp_ajax_nopriv_' ) ) {
continue;
}
$action = substr( (string) $hook_name, strlen( 'wp_ajax_nopriv_' ) );
$plugin = self::owning_plugin_for_hook( $hook_obj );
$nopriv_actions[] = array( 'action' => $action, 'plugin' => $plugin );
}
update_option( 'argus_wpd_ajax_inventory', array( 'checked_at' => current_time( 'mysql', true ), 'nopriv_actions' => $nopriv_actions ), false );
if ( ! empty( $nopriv_actions ) ) {
Argus_Findings::record(
'ajax_inventory',
'info',
array(
'what_happened' => 'Unauthenticated-reachable AJAX actions inventoried',
'why_it_matters' => 'wp_ajax_nopriv_* handlers are callable by anyone, logged in or not -- this is a completely normal, widely-used WordPress mechanism (contact forms, AJAX search, and many other legitimate features all use it), not inherently a problem.',
'what_argus_found' => sprintf( '%d action(s) found: %s', count( $nopriv_actions ), implode( ', ', array_map( function ( $a ) { return $a['action'] . ( $a['plugin'] ? ' (' . $a['plugin'] . ')' : '' ); }, $nopriv_actions ) ) ),
'when_it_happened' => current_time( 'mysql' ),
'why_suspicious' => 'This is an inventory, not a detection -- shown so you know your site\'s full unauthenticated attack surface in one place.',
'what_could_be_affected' => 'Depends on what each handler does -- review any you don\'t recognize.',
'what_should_you_do' => 'No action needed unless you see an action name you don\'t recognize from a plugin you don\'t remember installing.',
),
array( 'nopriv_actions' => $nopriv_actions )
);
}
return $nopriv_actions;
}
protected static function owning_plugin_for_hook( $hook_obj ) {
if ( ! isset( $hook_obj->callbacks ) || ! is_array( $hook_obj->callbacks ) ) {
return null;
}
foreach ( $hook_obj->callbacks as $priority_group ) {
foreach ( $priority_group as $cb ) {
$callback = $cb['function'] ?? null;
$plugin = Argus_REST_Inventory::owning_plugin( $callback );
if ( $plugin ) {
return $plugin;
}
}
}
return null;
}
}