WP Manifestindependent plugin directory
manifest / security / hlb-scoped-auth-passwords

Scoped Agent Credentials

Scope WordPress Application Passwords to named abilities and post types, with expiry and revoke.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/jdbg/hlb-scoped-auth-passwords/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

WordPress Application Passwords carry every capability the issuing user has, never expire, and can't be limited to a named ability or post type. This plugin adds that scoping layer on top of core's Application Passwords.

A credential can be limited to:

  • specific abilities (via the Abilities API)
  • specific post types
  • an expiry date
  • revocation at any time, effective immediately

Status

Core enforcement is implemented: expiry/revoke at auth time, ability and post-type scope at dispatch time. No admin UI yet; credentials are issued and managed through WP-CLI. Architecture decisions are tracked in decisions/.

Requirements

  • WordPress 6.9+ (Abilities API)
  • PHP 7.4+

Usage

wp hlb-sap issue 12 --name="Content agent" --abilities=my-plugin/export-users --post-types=post
wp hlb-sap issue 12 --name="Read-only reporting" --post-types=post,page --expires="+30 days"
wp hlb-sap list-credentials
wp hlb-sap revoke <uuid>
wp hlb-sap revoke <uuid> --delete

Omit --abilities or --post-types entirely to leave that dimension unrestricted; pass an empty value to allow none. A credential with neither flag set behaves like an ordinary Application Password with an expiry.

Scope boundaries

Post-type scope restricts REST routes for post-type content only (/wp/v2/posts, /wp/v2/pages, and any custom post type's route). It does not restrict other REST routes - /wp/v2/users, /wp/v2/media, /wp/v2/settings, /wp/v2/plugins, and so on are governed only by the credential's own WordPress capabilities, same as an unscoped Application Password. Ability scope only restricts calls through the Abilities API's run endpoint.

This plugin adds two extra dimensions on top of capabilities; it doesn't replace them. For a credential that should touch nothing outside a narrow set of abilities and post types, issue it to a low-privilege user as well - capabilities are still the floor.

Development

composer install
composer run lint

Testing

End-to-end tests boot a real WordPress instance via WordPress Playground and drive every enforcement path with actual HTTP requests: auth-time revoke/expiry/XML-RPC gating, and dispatch-time post-type and ability scope.

npm install
npx playwright install --with-deps chromium
npm run test:e2e

npm run playground:start boots the same environment for manual poking, at whatever URL it prints.