New Local Media logo New Local Media Work in Progress Open projects, products, and experiments.
More Projects!

Sudo ⛩️

A finished experiment in making WordPress ask for your password again before something dangerous happens. It did not work, and the seven ways around it are written up rather than patched, because the write-up is the point. Archived read-only — not for installation.

42 Last updated Aug 4, 2026 View Source for Sudo ⛩️

A Negative Result, Fully Documented

Sudo asked a simple question: could a plugin make WordPress demand your password again, right before something dangerous happens — deleting a user, installing a plugin, changing a critical setting — no matter who you are? After building it, testing it hard, and then auditing it adversarially, the answer came back no. Not the way this plugin went about it. The evidence for that answer is what the project actually produced.

Here is the idea that failed, in plain terms. To stop a dangerous request, the plugin first has to recognise one. So it asked a yes-or-no question about every incoming request — is this the delete-a-user request? That yes-or-no question is what the write-up calls a predicate: a test that looks at the request and answers true or false. WordPress core asks its own version of the same question to decide what the request actually does. Two separate questions, written by two different people, in two different places, both supposed to mean the same thing.

They did not mean the same thing. The audit found seven ways to slip past the gate, and each one is the same story: core asked its question slightly differently than the plugin asked its own. Core matched a web address while ignoring capital letters; the plugin matched while respecting them, so changing one letter to uppercase walked straight through. Core accepted a value from either the form data or the address bar; the plugin only looked at the form data, so moving it to the address bar made the gate blind. Core treated a save as "any POST request at all"; the plugin waited for a specific action name that never came. Neither side is wrong on its own — they simply drifted apart, and nothing in the system could notice they had.

The genuinely instructive part is why an enormous test suite never caught it. There were 1,308 unit tests, 243 integration tests, 112 end-to-end tests, PHPStan at level 6, Psalm, and a mandatory adversarial review before release. None of them found any of the seven, and — this is the point — none of them could have. A test looks something like build a fake request that means "delete a user", hand it to the gate, assert the gate stops it. But the fake request is built from the plugin’s own idea of what that request looks like. If that idea is wrong, the test builds the wrong request, hands it to a matching wrong gate, and passes — confidently, in green, forever. The test and the code under test were reading from the same incorrect script. Every one of the six problems was found only by opening WordPress core and the plugin’s matcher next to each other and reading them line by line.

The lesson generalises past this plugin: a test suite can only check that code agrees with your model of the world. When the model itself is wrong, more tests just means more confident wrongness. Nothing short of comparing your assumptions against the real thing will surface it.

Start with the architecture history for a plain-language walk through every approach the project tried, then the finding for the technical result and the narrow core primitive it argues for.

Related Repo: WordPress 2FA Ecosystem Documentation.

Repository Details

Owner
@dknauss
Source
dknauss/Sudo
CI
GitHub Actions
License
GPL-2.0
Last updated
Primary language
PHP
Stars
42
Sudo for WordPress — concluded ⛩️

Do not install this plugin. It contains seven verified high-severity bypasses of its own central claim, left documented rather than fixed because they are the finding. The implementation and test suites are retained read-only as the evidence those findings rest on — deleting them would leave assertions nobody could reproduce, which is the failure mode this project exists to document.

Screenshot Gallery

Selected screenshots from Sudo. Click any image to enlarge it.

Challenge page — the reauthentication interstitial shown before a gated action proceeds.
Plugins screen — the gate announcing itself before plugin management is attempted.
Settings tab — early-gate status, policy presets, session duration, and per-surface entry-point policies.
Gated Actions tab — every gated operation with its rule ID and covered surfaces.
Rule Tester tab — evaluate a representative request shape without executing it.
Access tab — grant and revoke the dedicated Sudo governance capabilities.
Dashboard widget — active sessions, policy summary, and recent privilege-action events.

Documentation

Documentation links and descriptions for Sudo.
Document Description
Architecture HistoryStart here — a short, plain-language walk through every approach the project tried, what each attempted, and where each ran out.
The FindingThe technical result, the six axes of predicate drift, and the narrow WordPress core primitive it argues for.
Audit Verification RecordIndependent verification of all seven high-severity bypasses against WordPress 7.0 source.
Post-MortemHow a heavily tested project failed to see what it had already diagnosed — 1,663 tests that could not catch a wrong predicate.
Security ModelThreat model and the boundaries the prototype never claimed to cover.
Upstream SourcesEvery third-party claim, with enclosing symbol, machine-checked.
Project StatusThe research-prototype classification and why it exists.
READMEThe conclusion in full — result, honest scope, and acknowledgements.