TL;DR: register_meta()
exposes meta fields in all REST API endpoints, which can lead to privacy leaks. To avoid that, call it conditionally. For an example, see r5219-meta and r5222-meta.
I ran into an undocumented and unexpected problem when registering custom post type meta fields for the REST API.
As of WordPress 4.7, there’s no way to register a meta field for a specific post type. Registering a field registers it for all post types, and registering it with show_in_rest => true
exposes it in all REST API endpoints.
That may seem harmless if you don’t stop to think about, but doing it could lead to unintentional privacy leaks. For example, an email_address
field might be perfectly safe to expose in one endpoint (e.g., something that’s already public like support@example.org), but exposing that same field on a different post type could be leaking someone’s private information.
Right now, there’s no officially-supported way to avoid that, other than using register_rest_field()
instead of register_meta()
.
register_rest_field()
isn’t a logical solution for post meta, though. With it, meta fields would not show up in the meta
tree of the response, where other meta fields are located, and where a client would expect to find them. Instead, they’d show up as top-level fields in the response, as if they were first-class post
object fields, or as if they were arbitrary fields (which is what I think register_rest_field()
is really intended for).
Having meta fields at the top-level also clutters the post item, making it harder to read, and annoying the crap out of grumpy, old, anal-retentive developers like me :)
So, in order to safely add meta fields inside the meta
tree where they belong, but without exposing them on endpoints where they don’t belong, I came up with an ugly workaround.
We can call register_meta()
conditionally, so that the meta fields are only registered during the specific API responses where we want to expose them. For all other API and non-API requests, it won’t be called at all, and the fields won’t be exposed.
You can see an example in r5219-meta and r5222-meta.
If you use something like this, though, I’d recommend keeping an eye on #38323-core, and migrating to the official solution when it becomes available.
Wow, always keeping us devs on our toes. I’m just getting into using the WP REST API and this post has saved me before I make a huge mistake and expose user personal data. Thank you for your post!
How to edit a post meta data in a Gutenberg Block? – Read For Learn