Skip to content

Harden update_block_text_content: void elements and attribute names - #18

Open
saarnilauri wants to merge 1 commit into
humanmade:mainfrom
saarnilauri:fix/harden-update-block-text-content
Open

Harden update_block_text_content: void elements and attribute names#18
saarnilauri wants to merge 1 commit into
humanmade:mainfrom
saarnilauri:fix/harden-update-block-text-content

Conversation

@saarnilauri

Copy link
Copy Markdown

Two small, defensive hardening fixes to the replace_text / textContent path.

1. Void elements can't hold text (bug)

update_block_text_content() wraps the new text as <tag …>text</tag> for the
block's first tag. When that tag is a void element (<hr>, <img>, <br>, …)
this emits invalid markup, e.g. replace_text on a core/separator produces
<hr class="wp-block-separator">text</hr>, which the block editor rejects.

The function now returns void-wrapped blocks unchanged, via a small
is_void_element() helper (self-contained list, no WP-version dependency).

2. Attribute-name re-emission (hardening)

Both update_block_text_content() and rebuild_inner_content() re-emit
attribute names straight from WP_HTML_Tag_Processor::get_attribute_names_with_prefix('').
The read-path lexer only excludes whitespace, =, / and > from a name, so a
stored name could contain quotes. This is not exploitable (without whitespace
or = there's no attribute breakout, and values are already esc_attr()'d), but
names that don't match [a-zA-Z0-9:_.-]+ are now skipped rather than reflected ,
belt-and-braces in case the lexer ever loosens.

Tests

  • test_update_block_text_content_leaves_void_elements_untouched fails on
    current main (emits <hr>…</hr>), passes with this change.
  • test_update_block_text_content_preserves_attributes confirms the
    attribute-name guard doesn't drop standard class/id attributes.

Verified in the wp-env PHPUnit suite: full suite green (107 tests). The
attribute-name change is hardening with no readily reproducible failing case, so
it has no dedicated red test.

Use of AI

The code changes were created with AI agent, the changes reviewed by me. Tests runned by me.

Two defensive fixes to the text-replacement path:

- Void elements (<hr>, <img>, <br>, …) can't contain text, so building
  <hr>text</hr> for a replace_text on e.g. core/separator produced
  invalid markup the editor rejects. update_block_text_content() now
  returns such blocks unchanged (new is_void_element() helper).

- Attribute names are re-emitted verbatim from WP_HTML_Tag_Processor in
  both update_block_text_content() and rebuild_inner_content(). The
  read-path lexer only excludes whitespace, `=`, `/` and `>` from names,
  so a stored name could carry quotes; not exploitable (no whitespace or
  `=` means no attribute breakout), but names that aren't
  [a-zA-Z0-9:_.-]+ are now skipped rather than reflected.

Adds tests: replace_text on a separator leaves it untouched, and
standard wrapper attributes survive a text replacement.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant