WP Manifestindependent plugin directory
manifest / developer / wp-hook-permissions

WP Hook Permissions

WP Hook Permissions is a must-use plugin that brings full transparency to the WordPress hook system. It tracks every `add_action()` and `add_filter()` call made by installed plugins and themes, attributes each callback to its source, and lets administrators allow or deny individual hooks per plugin — all without touching plugin code.

by Smartlogix · github.com/namithj/wp-hook-permissions · website

2stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/namithj/wp-hook-permissions/archive/refs/heads/main.zip

Tracks, attributes, and permission-gates WordPress hook callbacks at runtime.


[!WARNING] Proof of Concept

This plugin is an exploratory implementation intended to surface ideas and spark discussion around giving WordPress administrators granular visibility and control over hook callbacks.

The goal is to demonstrate what a more elaborate and more secure implementation could look like, and to invite feedback from the WordPress community on the approach, API surface, and threat model before investing in a fuller solution.


Overview

WP Hook Permissions is a must-use plugin that gives site administrators full visibility and control over the WordPress hook system. It passively tracks every add_action() and add_filter() call, attributes each callback to its source plugin or theme, and lets you allow or deny hooks on a per-plugin basis — without touching any plugin code.

Key Features

Feature Description
Runtime tracking Captures hook registrations on every request via a passive all hook listener
Permission gating Removes denied callbacks before they run; fail-open by default
Activation review modal Intercepts the Activate button and shows a grouped hook table before going live
Update monitoring Newly discovered hooks after a plugin update are denied by default until reviewed
Admin UI Tools → Hook Permissions with per-hook Allow/Deny toggles, grouped by category
Static scanner Tokenises PHP files to find hooks without executing code
Blocked-execution log Rolling audit trail of removed callbacks (capped at 100 entries)
permissions.json support Plugin authors can document hook intent; notes surface in the UI

Installation

From a release zip (recommended)

  1. Download wp-hook-permissions-<version>.zip from the Releases page.
  2. Unzip and upload the wp-hook-permissions/ directory to wp-content/mu-plugins/.
  3. Place (or merge) plugins.php in wp-content/mu-plugins/ — it auto-loads all MU plugins that follow the <slug>/<slug>.php convention.
  4. Must-use plugins activate automatically; no manual activation needed.

From Git

cd wp-content/mu-plugins
git clone https://github.com/smartlogix/wp-hook-permissions.git wp-hook-permissions

Then add the universal loader if it doesn't exist:

# wp-content/mu-plugins/plugins.php
<?php
defined( 'ABSPATH' ) || exit;
foreach ( glob( __DIR__ . '/*', GLOB_ONLYDIR ) as $dir ) {
    $file = $dir . '/' . basename( $dir ) . '.php';
    if ( file_exists( $file ) ) { require_once $file; }
}

Directory Structure

wp-hook-permissions/
├── wp-hook-permissions.php   # Plugin header + bootstrap
├── src/
│   ├── Plugin.php            # Service container
│   ├── PermissionStore.php   # Options-backed permission map
│   ├── ExecutionController.php
│   ├── HookTracker.php
│   ├── Logger.php
│   ├── UpdateMonitor.php
│   ├── Admin/
│   │   ├── ActivationGuard.php
│   │   ├── Assets.php
│   │   ├── Notices.php
│   │   └── UI.php
│   ├── Contracts/
│   ├── Scanner/
│   │   ├── RuntimeTracker.php
│   │   └── StaticScanner.php
│   └── Utils/
│       ├── CallbackHasher.php
│       ├── HookGrouper.php
│       ├── PermissionsJson.php
│       └── SourceResolver.php
├── assets/
│   ├── css/admin.css
│   ├── css/activation-guard.css
│   └── js/activation-guard.js
├── tests/
│   ├── bootstrap.php
│   ├── Unit/
│   ├── Integration/
│   └── Fixtures/
├── uninstall.php
├── composer.json
├── phpcs.xml.dist
└── phpunit.xml.dist

How It Works

Fail-open permission model

Condition Result
Plugin not yet in inventory Allowed
Plugin known, hook not mapped Allowed
Explicit true stored Allowed
Explicit false stored Blocked

Only an explicit false in the permission store blocks a callback. This preserves all existing functionality until the administrator makes a deliberate decision.

Bypass hooks

The following core bootstrap hooks are never gated to prevent accidental site breakage:

muplugins_loaded, plugins_loaded, setup_theme, after_setup_theme, init, wp_loaded, shutdown, all

Activation guard flow

User clicks Activate
      │
      ▼
JS intercepts link
      │
      ▼
AJAX preflight → StaticScanner scans PHP files → returns grouped hook list
      │
      ▼
Modal opens — user reviews Allow/Deny per hook
      │
      ▼
"Accept & Activate" → AJAX saves permissions → server issues one-time token
      │
      ▼
JS redirects to WP activation URL + token → server validates + consumes token
      │
      ▼
WP activates plugin/theme normally

Development

Requirements

  • PHP 7.4+
  • Composer

Setup

cd wp-hook-permissions
composer install

Available scripts

Command Description
composer phpcs Run PHP_CodeSniffer (WordPress-Extra + Docs + Core)
composer phpcbf Auto-fix PHPCS violations
composer phpunit Run PHPUnit test suite
composer phpstan Run PHPStan static analysis

Testing

composer phpunit
# Run a single suite:
vendor/bin/phpunit --testsuite Unit
vendor/bin/phpunit --testsuite Integration

permissions.json

Plugin authors can ship a permissions.json at their plugin root to document hook intent. Descriptions appear as notes in the Hook Permissions UI and the activation modal. This file never auto-grants permissions.

{
    "init":       "Registers custom post types and taxonomies.",
    "admin_init": "Loads plugin settings page."
}

Hooks & Filters

Hook Type Description
wphp/loaded action Fires after the plugin has fully booted
wphp/hook_groups filter Override/extend the hook → group mapping used in the UI

Changelog

0.1.0

  • Initial release

License

GPL-2.0-or-later — see LICENSE.