Skip to content

Stop editorial metadata leaking to unauthorised REST readers - #1036

Merged
GaryJones merged 1 commit into
developfrom
GaryJones/rest-editorial-metadata-read-exposure
Aug 18, 2026
Merged

GaryJones merged 1 commit into
developfrom
GaryJones/rest-editorial-metadata-read-exposure

Conversation

@GaryJones

@GaryJones GaryJones commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Since 0.10.0, the Editorial Metadata module registers its fields with register_post_meta( … 'show_in_rest' => true … ) so that Gutenberg can save them over the REST API. That flag is symmetric: it also exposes the values on read. Because a published post is readable by everyone, every editorial metadata field on every published post, including fields an editor explicitly marked as not viewable, was served to anonymous, unauthenticated clients. The collection endpoint (/wp/v2/posts) returned them in bulk, so an attacker did not even need to know a post ID.

The auth_callback supplied with the registration is correct, but it governs writes only. Core exposes show_in_rest meta on read to anyone who can read the object, and there is no per-field read gate in core meta, so the write-side callback never applied here. This is CWE-200 information disclosure; the impact is contextual and depends on what a newsroom stores in those fields (source identities, contact details, legal notes).

The fix keeps show_in_rest intact, so saving from the block editor is unaffected, and adds a rest_prepare_{post_type} filter that strips the editorial metadata keys from responses for readers who cannot edit the post. The capability check is per-post so the collection endpoint is covered too, and it mirrors the existing pattern already used by the Custom Status module (register_rest_api_filters + rest_prepare_{post_type}). Editors continue to receive the fields, so the editor keeps working.

An integration test asserts both halves of the contract: an anonymous read must not contain the keys, and an editor's read must still return the stored value.

The version bump, CHANGELOG entry and POT regeneration are intentionally left out of this PR; they will be handled on the separate release branch.

Test plan

  • composer test:integration -- --filter EditorialMetadataTest passes, including test_rest_read_hides_editorial_metadata_from_unauthorised_users
  • Anonymous GET /wp-json/wp/v2/posts/<id> on a published post with editorial metadata no longer returns the _ef_editorial_meta_* keys
  • An editor still sees the fields in the block editor and can save them

@GaryJones
GaryJones requested a review from a team as a code owner August 18, 2026 10:52
@GaryJones GaryJones self-assigned this Aug 18, 2026
@GaryJones GaryJones added the type: bug Something isn't working label Aug 18, 2026
@GaryJones GaryJones added this to the Next milestone Aug 18, 2026
@GaryJones
GaryJones force-pushed the GaryJones/rest-editorial-metadata-read-exposure branch 2 times, most recently from 8a9445b to 0b6dedf Compare August 18, 2026 10:57
@GaryJones GaryJones changed the title Stop editorial metadata leaking to REST readers (0.11.1) Stop editorial metadata leaking to unauthorised REST readers Aug 18, 2026
Registering the editorial metadata fields with show_in_rest lets Gutenberg
save them, but the flag also exposes their values on read to anyone who can
read the post. A published post is public, so every editorial metadata field
on every published post, including fields an editor marked as not viewable,
was served to anonymous clients over the REST API. The meta auth_callback
guards writes only and never applied to reads.

Add a rest_prepare_{post_type} filter that strips the editorial metadata keys
from responses for readers who cannot edit the post, mirroring the write-path
registration's supported post types. The capability check is per-post so the
collection endpoint, which returns many posts at once, is covered too. Editors
still receive the fields, so the block editor keeps working.
@GaryJones
GaryJones force-pushed the GaryJones/rest-editorial-metadata-read-exposure branch from 0b6dedf to b5c9f83 Compare August 18, 2026 13:49
@GaryJones
GaryJones merged commit dbe856c into develop Aug 18, 2026
10 checks passed
@GaryJones
GaryJones deleted the GaryJones/rest-editorial-metadata-read-exposure branch August 18, 2026 14:12
@GaryJones GaryJones mentioned this pull request Aug 18, 2026
2 of 3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant