Fix stored XSS via unescaped Webmention-derived comment meta#613
Merged
Conversation
Parser-derived author metadata (avatar/url) from unauthenticated Webmentions was stored unsanitized and rendered unescaped in the comment edit metabox, allowing attribute-breaking payloads to execute JavaScript in a moderator/admin wp-admin session. Harden both layers: * Sanitize comment meta on store via register_meta() sanitize callbacks (esc_url_raw for URL meta, sanitize_key/sanitize_text_field for the rest) so the database stays clean. * Escape all output in edit-comment-form.php and the remaining template sinks (single-comment view, endpoint message/form, reaction heading), including the public comment.php where comment_author_url was echoed raw into an href and link text. Add regression tests covering both storage sanitization and output escaping. Bump version to 5.8.1.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a stored XSS reachable from unauthenticated Webmentions. Parser-derived author metadata (
avatar,url) from a crafted source page was stored unsanitized and rendered unescaped into HTMLvalueattributes in the comment edit metabox. When a moderator/administrator opens the comment, an attribute-breaking payload executes JavaScript in their privileged wp-admin session.Source → sink:
includes/handler/class-mf2.phpparses attacker-controlledu-photo/u-url(no validation)includes/entity/class-item.phpstores them asavatar/urlcomment metatemplates/edit-comment-form.phpechoed them raw intovalue="..."The meta was not sanitized on store either —
register_meta()had nosanitize_callback.Fix (defense in depth)
Sanitize on store — added
register_meta()sanitize callbacks inclass-receiver.php:esc_url_rawfor URL meta:avatar,url,webmention_source_url,webmention_target_url,webmention_vouch_urlsanitize_keyforprotocol,sanitize_text_fieldforwebmention_last_modifiedwebmention_target_fragment/webmention_response_code/webmention_voucheduntouched — they feed dedupe meta-queries/comparisons and are never rendered to HTML.Escape on output — escaped every field in
edit-comment-form.phpplus other unescaped template sinks found while auditing:templates/comment.php—comment_author_urlwas echoed raw into anhrefand link text on a public page (a second XSS vector) →esc_url/esc_htmlapi-message.php,comments.php,comment-form.php,endpoint-form.phpOutput escaping is needed independently because sanitize callbacks only apply to new writes; already-stored rows still need escaping on render.
Tests
tests/phpunit/tests/class-test-admin-metabox.phpcovers storage sanitization and output escaping. Confirmed it fails against the unfixed code (emits a live<script>breakout) and passes with the fix.Version
Bumped to 5.8.1 (5.8.0 is already released) with changelog entries.