Severities and Rules
Each finding is produced by a rule. A rule has an ID, a title, a fixed severity, an explanation of why the problem matters, fix advice and a link to the relevant WordPress documentation.
Severities#
| Severity | Meaning |
|---|---|
| Critical | Logged-out visitors or subscribers can run something that may change data. Fix immediately. |
| High | Destructive abilities exposed to remote clients, or writable by contributors and authors. Fix soon. |
| Medium | Missing annotations, loose or missing input validation, or an orphaned category. Fix in the next release. |
| Low | Quality issues: missing output schema, short description. |
| Info | Not a problem. Tells you which channels an ability is exposed on, so you know the attack surface. |
Built-in rules#
| Severity | Rule ID | Title | Fires when |
|---|---|---|---|
| Critical | low-privilege-write | Visitors or subscribers can run an ability that may change data | The permission check passes for Anonymous or Subscriber and the ability is not annotated read-only. |
| High | destructive-exposed | Destructive ability is exposed to remote clients | The ability is annotated destructive and is effectively exposed to REST or MCP. |
| High | author-write | Contributors or authors can run a destructive or unannotated ability | The permission check passes for Contributor or Author and the ability is destructive or has no annotations. |
| Medium | missing-annotations | Missing behavior annotations | Neither readonly nor destructive is set. |
| Medium | input-schema | Input is not strictly validated | There is no input schema, or an object schema without additionalProperties: false. |
| Medium | unregistered-category | Category is not registered | The ability’s category is no longer registered. |
| Low | output-schema | No output schema | There is no output schema. |
| Low | short-description | Description is too short | The description is empty or under 20 characters. |
| Info | exposure-summary | Exposed to remote clients | The ability is exposed, listing each channel and where its exposure comes from. |
How a finding is written#
Every finding includes:
- Message: what was observed, for example “The permission check passes for: Anonymous, Subscriber. The ability is not annotated read-only.”
- Why it matters: the risk in plain language.
- How to fix: concrete advice, such as using
current_user_can( 'edit_post', $input['id'] )instead of__return_trueoris_user_logged_in(), or addingreadonly => truewhen the ability really changes nothing. - Documentation: a link to the Abilities API handbook, the schema guide, or the relevant Make WordPress post.
Fingerprints#
Each finding has a stable fingerprint made of its rule ID and ability name. The History tab, the “new since last audit” badge and the email alerts all compare fingerprints, so a problem you already know about is never counted as new again.
Why some rules rarely fire#
Core refuses to register an ability whose category does not exist and requires a non-empty description. So unregistered-category only fires when a category is removed after its abilities registered, and short-description in practice means “under 20 characters”.
Adding your own rules#
Developers can add, remove or replace rules with the abau_rules filter. See Hooks & Filters.
