VGT Throne Guard
Throne Guard is a WordPress hardening plugin that removes the most dangerous capabilities from the Administrator role and places them behind a separate Master role gated by a Superkey.
by VisionGaia Technology · github.com/visiongaiatechnology/throne-guard
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/visiongaiatechnology/throne-guard/archive/refs/heads/main.zipReadme
🏰 Throne Guard — Admin is not God
"Administrator is a role, not a throne." AGPLv3+ — Open Source. Built for sites that will be compromised eventually.
⚠️ DISCLAIMER: EXPERIMENTAL R&D PROJECT
This project is a Proof of Concept (PoC) and part of ongoing research and development at VisionGaia Technology. It is not a certified or production-ready product.
Use at your own risk. The software may contain security vulnerabilities, bugs, or unexpected behavior. It may break your environment if misconfigured or used improperly.
Do not deploy in critical production environments without thorough code review. Throne Guard modifies WordPress capability assignments — if you lock yourself out of the Master role without recording your Superkey, recovery requires direct database access.
Found a vulnerability or have an improvement? Open an issue or contact us.
📋 Changelog — V2.5.1
- Pre-Flight WAF: Scoped to admin and MCP routes only — no more collateral damage in frontend uploads
- Upload Jail:
.htaccessnow uses append-with-markers instead of overwrite — preserves existing custom rules (CDN, WebP, rewrites) - Session Gating: Ephemeral server-side token validation with strict
hash_equalscomparison — immune to client-side cookie manipulation - Exception Hierarchy:
ValidationException/SecurityException/StorageExceptionwith asymmetric client/log messaging — users never see internal details - CSRF Tokens: Single-use
bin2hex(random_bytes(32))tokens on top of WordPress nonces for all state-changing operations
🔍 What is Throne Guard?
Throne Guard is a WordPress hardening plugin that removes the most dangerous capabilities from the Administrator role and places them behind a separate Master role gated by a Superkey.
It is built on a single premise: in 9 out of 10 WordPress compromises, the attacker ends up with Administrator access. Vulnerable plugins, phished passwords, stolen session cookies — the Administrator account is the pivot point of almost every real-world WordPress hack.
Throne Guard assumes the Administrator will be compromised and makes sure that even then, the attacker cannot install plugins, switch themes, create users, or deactivate Throne Guard itself.
Traditional WordPress Hardening:
→ 2FA on admin login — prevents credential theft
→ Login rate limiting — slows brute force
→ IP whitelisting — limits attack surface
→ Still: Admin compromise = full site compromise
Throne Guard Approach:
→ Admin ≠ God — strip toxic capabilities
→ Separate Master role — elevated functions isolated
→ Superkey gate — bcrypt-hashed, never in session
→ Plugin stealth — Throne Guard invisible to Admins
→ Deactivation guard — cannot be disabled without Master
🏛️ Architecture
Incoming Admin Request
↓
Pre-Flight WAF (Upload Inspection)
→ Toxic extensions (.php, .phar, .phtml, .pht...) blocked at MS 0
→ Scoped to admin routes — zero frontend collateral damage
→ Double-extension detection (shell.phar.jpg)
↓
Backend Lock (Zero-Trust Session Gating)
→ Master-capability check
→ Ephemeral token + server-side meta validation
→ 2-hour expiration enforced server-side
→ AJAX routes gated separately (no bypass)
↓
CSRF + Nonce Double Layer
→ WordPress nonce (action-scoped)
→ Single-use CSRF token from user meta
→ Both required for all state changes
↓
Capability Enforcement
→ Administrator: stripped of toxic capabilities
→ Master: full control, gated by Superkey
→ editable_roles filter: non-Masters cannot promote to Master
→ all_plugins filter: Throne Guard invisible to non-Masters
↓
Upload Jail (Auto-Healed)
→ wp-content/uploads/.htaccess maintained on every dashboard load
→ Append-with-markers — preserves existing custom rules
→ PHP execution disabled at webserver level
↓
Secure Vault Upload
→ MIME + magic byte + IMAGETYPE triple-check
→ GD re-encoding — all metadata and payloads stripped
→ 0600 permissions + 0700 directory + realpath jail
→ Cryptographically random filenames
🧩 Module Matrix
☢️ Admin Neutering
Strips toxic capabilities from the Administrator role. Configurable via dashboard, enforced at WordPress capability level. Requires Superkey confirmation for every change.
| Capability | Risk if Retained | Default |
|---|---|---|
activate_plugins |
Install backdoor plugins | Stripped |
delete_plugins |
Remove security plugins | Stripped |
install_plugins |
Upload malicious plugins | Stripped |
edit_plugins |
Inject code into existing plugins | Stripped |
update_plugins |
Downgrade to vulnerable versions | Stripped |
switch_themes |
Activate malicious themes | Stripped |
edit_themes |
Inject code into themes | Stripped |
install_themes |
Upload malicious themes | Stripped |
delete_themes |
Remove legitimate themes | Stripped |
update_themes |
Downgrade to vulnerable versions | Stripped |
edit_users |
Change other users' passwords/roles | Stripped |
delete_users |
Remove legitimate admins | Stripped |
create_users |
Create persistent backdoor accounts | Stripped |
promote_users |
Elevate accounts to admin | Stripped |
All capabilities are re-assignable to Administrator via the dashboard, provided the Superkey is presented.
🔐 Superkey Gate
Zero-trust session gating for the Master role.
| Feature | Detail |
|---|---|
| Storage | password_hash() with PASSWORD_DEFAULT (bcrypt) |
| Verification | password_verify() — timing-safe |
| Minimum Length | 12 characters |
| Session Token | Ephemeral: expiration\|bin2hex(random_bytes(32)) |
| Server Binding | Identical string stored in user meta and cookie — client-side manipulation immediately detectable |
| Validation | hash_equals() strict comparison — timing-attack resistant |
| Expiration | 2 hours, server-side enforced via meta timestamp |
| Cookie Flags | httponly, secure, samesite=Strict |
| Cleanup | Session meta auto-deleted on clear_auth_cookie hook |
| Anti-Bruteforce | sleep(2) penalty on failed Superkey attempts |
Recovery if Superkey is lost:
DELETE FROM wp_options WHERE option_name = 'mcp_superkey_hash';
Direct database access required. No email recovery, no security questions. By design.
🚪 Pre-Flight WAF
Intercepts toxic file uploads before WordPress processes them.
| Feature | Detail |
|---|---|
| Scope | is_admin() or MCP action routes only — no frontend impact |
| Detection | Extension allowlist + regex double-extension check |
| Blocked Extensions | .php, .phtml, .phar, .shtml, .php3–.php8, .pht, .cgi, .pl, .asp, .aspx, .jsp |
| Double-Extension | shell.phar.jpg — blocked via regex pattern against any toxic extension in the filename |
| Response | HTTP 403 + immediate die() — no WordPress processing whatsoever |
| Logging | All interceptions written to error_log with filename |
🏗️ Upload Jail
Auto-maintained .htaccess in wp-content/uploads/ to disable PHP execution at the webserver level.
# BEGIN VGT REDTEAM
<FilesMatch "\.(?i:php|phtml|phar|shtml|php3|php4|php5|pht|cgi|pl|asp|aspx|jsp)">
Require all denied
Order allow,deny
Deny from all
</FilesMatch>
<IfModule mod_php.c>
php_flag engine off
</IfModule>
<IfModule mod_php7.c>
php_flag engine off
</IfModule>
<IfModule mod_php8.c>
php_flag engine off
</IfModule>
# END VGT REDTEAM
Self-healing: Re-applied on every dashboard load if markers are missing or tampered with.
Coexistence: Appended using # BEGIN / # END markers — preserves existing custom rules (CDN, WebP, redirects).
Nginx/Caddy fallback: index.php injected into vault directory to prevent directory listing.
🔒 Secure Vault Upload
Jailed, re-encoded image uploads with aggressive payload stripping. Accessible only to Master users.
| Stage | Check |
|---|---|
| 1. MIME Check | finfo binary inspection |
| 2. Magic Byte Check | getimagesize() type verification |
| 3. Cross-Validation | MIME type ↔ IMAGETYPE_* constant match — polyglot vectors blocked |
| 4. Memory Budget | Pre-calculated image memory requirement vs. PHP memory_limit |
| 5. Re-Encoding | GD imagecreatefrom* → image*() — all EXIF metadata and embedded payloads stripped |
| 6. Filesystem Jail | realpath validation, 0700 directory, 0600 file permissions |
| 7. Filename | bin2hex(random_bytes(16)) — original filename discarded entirely |
Allowed formats: JPEG, PNG, WebP, GIF Max file size: 5MB
🛡️ Plugin Stealth & Deactivation Guard
Throne Guard actively conceals itself from unauthorized users:
- Invisible to Administrators:
all_pluginsfilter removes Throne Guard from the plugin list for any user withoutmcp_master_access - Deactivation blocked: The
deactivate_pluginhook fireswp_die()with HTTP 403 for unauthorized deactivation attempts - Role hidden: The Master role is not visible in user edit forms for non-Master users via
editable_rolesfilter
An attacker with full Administrator access sees a WordPress installation with no Throne Guard present. They cannot deactivate what they cannot see.
🔑 CSRF + Nonce Double Layer
Every state-changing operation requires both:
- WordPress nonce — action-scoped, time-limited (
wp_verify_nonce) - CSRF token —
bin2hex(random_bytes(32))stored in user meta, single-use, consumed on verify viadelete_user_meta
Both must validate. The CSRF token is deleted after a single successful verification — replay is impossible even within the nonce's validity window.
🔖 CSP Headers
Strict Content-Security-Policy with per-request nonces injected on the frontend only (admin backend is exempt to avoid breaking WordPress core inline scripts):
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}';
style-src 'self' 'nonce-{random}'; object-src 'none';
base-uri 'self';
Frontend script output uses JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT encoding and DOM construction exclusively via document.createElement + textContent — no innerHTML.
🚨 Exception Hierarchy
Throne Guard uses a typed exception hierarchy with asymmetric error messaging:
| Exception | Visible to User | Logged |
|---|---|---|
ValidationException |
Full message shown verbatim | No |
SecurityException |
Generic "request rejected" message | Yes — full detail to error_log |
StorageException |
Generic "server error" message | Yes — full detail to error_log |
Internal error details never leak to the client. Users see only what is safe to expose.
⚙️ Threat Model
Throne Guard is defense in depth. It does not replace existing security measures — it adds a layer that becomes relevant specifically when your other layers have failed.
What Throne Guard protects against
| Threat | Mitigation |
|---|---|
| Admin credential theft → backdoor plugin install | Admin lacks install_plugins |
| Admin session hijack → theme code injection | Admin lacks edit_themes |
| Admin compromise → persistent backdoor account | Admin lacks create_users |
| Admin compromise → privilege escalation | Admin cannot see or promote to Master role |
| File upload → PHP execution in uploads directory | Pre-Flight WAF + Upload Jail |
| Attacker discovering security tooling | Throne Guard hidden from non-Masters |
| Attacker disabling security plugin | Deactivation blocked at hook level |
What Throne Guard does NOT protect against
| Threat | Reason |
|---|---|
| Server-level RCE | WordPress capability checks are irrelevant once the attacker has shell |
| Direct database modification | wp_options write access bypasses all WordPress logic |
| Master user compromise | Master is the top of the chain — protect it with 2FA |
| Supply chain attacks against Throne Guard | Always verify the plugin checksum |
| WordPress core vulnerabilities | Keep WordPress updated |
🚀 Installation
# 1. Clone into WordPress plugins directory
cd /var/www/html/wp-content/plugins/
git clone https://github.com/visiongaiatechnology/throne-guard