Skip to content

Strip HTML from filter-supplied editorial metadata CSS#945

Merged
GaryJones merged 2 commits intodevelopfrom
GaryJones/escape-editorial-metadata-css
Apr 24, 2026
Merged

Strip HTML from filter-supplied editorial metadata CSS#945
GaryJones merged 2 commits intodevelopfrom
GaryJones/escape-editorial-metadata-css

Conversation

@GaryJones
Copy link
Copy Markdown
Contributor

Summary

Editorial Metadata builds a small CSS block to give each of its manage-posts columns a sensible minimum width. The rules are assembled into a \$css_rules array, passed through the ef_editorial_metadata_manage_posts_css_rules filter, then echoed inside a <style> block with no escaping. For Edit Flow's own defaults the output is safe, but because the filter allows arbitrary modification there's nothing stopping a misbehaving plugin or theme from slipping a literal </style> sequence into a selector or declaration — and that would break out of the style block and let whatever followed it be parsed as HTML in the admin.

This PR runs both the selector and each declaration through wp_strip_all_tags() before echoing them. That removes any HTML tag a filter callback may have introduced, including the </style> breakout, whilst leaving valid CSS syntax intact. esc_html() would achieve the same breakout protection but would also encode quotes and ampersands, corrupting any legitimate url("…") declarations a plugin might have added via the same filter.

Test plan

  • Load Posts or Pages with Editorial Metadata columns enabled and confirm the min-width rules still apply as before
  • Register a throw-away callback on ef_editorial_metadata_manage_posts_css_rules that returns a rule containing </style><script>alert(1)</script>; confirm the rendered style block contains neither the </style> nor the script tag

The admin list-table CSS for editorial metadata columns is assembled
into a $css_rules array, passed through an
ef_editorial_metadata_manage_posts_css_rules filter, then echoed
inside a <style> block with no escaping. The default selector and
declarations are safe, but a filter callback from another plugin or
theme could smuggle a literal </style> sequence into the keys or
values and break out of the style block into arbitrary HTML.

Each property and declaration is now passed through
wp_strip_all_tags() before being echoed. That removes any HTML tag
the filter may have introduced (including the </style> breakout)
whilst leaving valid CSS syntax untouched — esc_html() would encode
quotes and ampersands, which would corrupt legitimate rules such as
url("…") declarations a plugin might legitimately add.
@GaryJones GaryJones requested a review from a team as a code owner April 23, 2026 23:32
Replace the manual echo of a <style> block with wp_add_inline_style,
attached to the edit_flow-editorial_metadata-styles handle that is
already enqueued on the same gate immediately above. This keeps the
output in the style pipeline WordPress manages rather than injecting
markup mid-admin_enqueue_scripts, and it also drops the remaining
phpcs EscapeOutput suppression.

The wp_strip_all_tags defences on the filter-supplied selectors and
rules are retained: wp_add_inline_style does not escape the string
it is handed, so an injected closing </style> tag would still need
to be stripped to prevent breakout.
@GaryJones GaryJones merged commit 4909073 into develop Apr 24, 2026
10 checks passed
@GaryJones GaryJones deleted the GaryJones/escape-editorial-metadata-css branch April 24, 2026 00:00
@GaryJones GaryJones added this to the Next milestone Apr 24, 2026
@GaryJones GaryJones self-assigned this Apr 24, 2026
@GaryJones GaryJones mentioned this pull request Apr 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant