All skills
wordpress avatar

/wp-abilities-verify

@20324d2 official
by wordpresswordpress/agent-skills2.2k stars
327

Verify a WordPress plugin's Abilities API registrations: enumerate abilities, check that callback behavior matches each annotation's claim (the adversarial readonly-but-writes detection), validate permissions and schemas, and validate audit documents produced by wp-abilities-audit.

Use this Skill: https://skilld.dev/gh/wordpress/agent-skills/wp-abilities-verify

This session only. Nothing lands on disk.

referencesaudit-schema-validation.md

≈1.3k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Audit Schema Validation

How wp-abilities-verify validates an audit document produced by wp-abilities-audit. The canonical schema (field tables, types, invariants, known limitations) lives in ../../wp-abilities-audit/references/audit-schema.md — this reference covers only the validation procedure: how to extract the YAML, what checks to run in what order, and how to report results.

If a field type or shape question is not answered here, look in the canonical schema. Do NOT duplicate field tables in this file — the canonical is the single source of truth.

Why verify owns the validator

Verify fails fast on a malformed audit so the rest of its procedure can assume well-formed input. Audit produces; verify validates the production. Co-locating the validator with verify keeps the "validate audit" step in the same procedure as "validate registered abilities" and lets a single run produce one consolidated report.

Step 1 — extract the YAML

The audit doc is a markdown file with a single fenced ```yaml block containing the structured fields:

# Scan for the ```yaml fence and capture until the closing ``` fence.
awk '/^```yaml$/{f=1;next} /^```$/{f=0} f' <audit-doc.md> > /tmp/audit.yaml

If the audit has multiple YAML blocks (it shouldn't, but defensively), take the first one with proposed_abilities as a top-level key.

Parse with any YAML library — js-yaml from Node, yaml (Python), or yq from the command line. None of the canonical fields require non-standard YAML features (no anchors, no aliases), so a plain yaml.load is sufficient.

Step 2 — validate against the canonical schema

Apply the field-shape rules defined in ../../wp-abilities-audit/references/audit-schema.md. Specifically:

  1. Every required top-level field is present and non-empty (see "Top-level fields" in the canonical).
  2. capability_gate matches one of the legal shapes (single string, {read, write} object, or — with WARN per the canonical's "Known limitations" — the legacy slash-separated string).
  3. Every entry in proposed_abilities has every required per-ability field with the right type (see "proposed_abilities" in the canonical).
  4. Each ability's annotations block has all three booleans (readonly, destructive, idempotent) as actual booleans — string "true" / "false" is FAIL (indicates a quoting bug).
  5. Each ability's backing is either an object with the canonical fields or null; null is WARN, not FAIL (it's intentional gap output).

Missing required field → FAIL. Wrong type → FAIL. Legacy capability_gate slash-string → WARN.

Step 3 — whole-audit invariants

Run these after per-field validation passes:

Exactly 0 or 1 abilities with reference_ability: true

Count abilities where reference_ability is true. More than 1 → FAIL (the schema permits at most one reference; multiple are ambiguous for implementers picking a starting point).

const refCount = audit.proposed_abilities.filter(a => a.reference_ability === true).length;
if (refCount > 1) fail("multiple abilities claim reference_ability: true");

Every backing: null ability appears in surfaced_gaps

Per the canonical's "Known limitations": a null backing is intentional gap output and MUST be paired with a matching surfaced_gaps entry.

const gapNames = new Set((audit.surfaced_gaps || []).map(g => g.name));
for (const ability of audit.proposed_abilities) {
  if (ability.backing === null && !gapNames.has(ability.name)) {
    fail(`ability ${ability.name} has backing: null but is missing from surfaced_gaps`);
  }
}

excluded_from_mvp and surfaced_gaps may be empty

Both are optional; empty arrays are legal. Missing entirely → WARN (schema expects them, even if empty).

Step 4 — emit the report section

Each check goes into the "Audit doc validation" section of the run's final report:

## Audit doc validation

| Check | Result | Detail |
|---|---|---|
| Top-level required fields | OK | All 7 required fields present |
| `capability_gate` shape | OK | string (single-cap) |
| Per-ability fields | WARN | 1 ability has `backing: null` (intentional) |
| `reference_ability` uniqueness | OK | 1 ability marked |
| `surfaced_gaps` consistency | OK | all `backing: null` entries present |

A single FAIL in this section makes the whole run FAIL; verify cannot meaningfully continue without a trustworthy audit. WARN entries don't block the rest of the procedure.

The procedure is manual-but-deterministic: follow the steps above in order, emit the report section, and fail fast on any missing required field. A future contribution may add a deterministic CLI helper that extracts the YAML fence and applies the rules end-to-end; until that exists, the steps above are the contract.

Escalation

If the validator rejects an audit that's actually well-formed, the canonical schema in ../../wp-abilities-audit/references/audit-schema.md has evolved. Update this file's procedure to match (likely adding a new invariant or relaxing a field rule). Don't loosen the validation in isolation — the canonical schema is the contract; this file is the enforcer.

Source: SKILL.md on GitHub

1 alert2mo3 checks · Risk HIGH
  • Gen Agent Trust Hub2mo

    This skill facilitates the verification of WordPress plugins but introduces a high-risk security vulnerability by instructing the agent to execute arbitrary shell commands defined within the target plugin's metadata files (AGENTS.md). This behavior allows a malicious repository to achieve remote code execution (RCE) on the agent's host system during the audit process. Additionally, the skill lacks sanitization for data ingested from audit documents used in environment seeding and execution.

  • Socket2mo

    No alerts

  • Snyk2mo

    Risk: LOW · No issues

Signed by skilld at 20324d2. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 3 months ago
Other metadata
compatibility
Targets WordPress 7.0+ plugins (PHP 7.4.0+). Requires a runnable environment (wp-env, docker-based dev stack, or equivalent) for runtime mode; static mode runs entirely from the plugin checkout with no env. Filesystem-based agent with bash + node.
  • Security
  • wordpress
  • php
  • abilities-api
  • verification
  • schema-validation
  • permissions
  • static-analysis

README badge

README badge for wordpress/agent-skills/wp-abilities-verify

Checks WordPress plugin Abilities API registrations for correctness: verifies readonly and destructive claims against callback behavior (catching writes hidden in readonly abilities), validates permission gates and input schemas, and confirms audit documents. Runs in static mode (source inspection only) or runtime mode (live environment execution with permission roundtrip and idempotency checks).

Generated from the current SKILL.md.

Does this skill check if a readonly ability actually writes to the database?
Yes. The adversarial correctness check reads callback bodies and flags readonly abilities that perform writes via $wpdb, update_option, or non-GET delegates—a critical security issue because agents plan actions based on ability annotations.
Can I run this skill without a WordPress environment?
Yes. Static mode runs entirely from the plugin checkout with no environment needed. Runtime mode requires a runnable environment (wp-env, Docker, or equivalent) and catches additional issues like permission roundtrips and idempotency regressions that static mode cannot.
What does this skill require as input?
The plugin checkout path, the mode (static or runtime), and optionally an audit document path and report output path. For runtime mode, you must also provide the env-up command from the plugin's AGENTS.md.
Can this skill validate audit documents?
Yes. If you provide an audit document path, the skill validates it against the canonical schema, checks for missing fields, and cross-references registered abilities against the audit's declared gates.
What output does this skill produce?
A structured markdown report with tables showing each ability's annotation correctness, permission gates, schema lints, and error-code vocabulary, ending with an overall PASS, WARN, or FAIL verdict.

Generated from the current SKILL.md. These answers refresh after source changes.