Make WordPress Core

Opened 2 years ago

Closed 6 days ago

Last modified 5 days ago

#62024 closed defect (bug) (duplicate)

wp_kses_post incorrectly escapes "<" attributes values

Reported by: jernstjernst Owned by:
Priority: normal Milestone:
Component: Formatting Version: 5.0
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses: coding-standards

Description

Hello,

We are trying to use wp_kses everywhere we output as recommended. However, we encountered the following issue: 

Example:

<?php
echo wp_kses_post('<button data-glide-dir="<">&lt;</button>")
?>

Expected result:

<button data-glide-dir="<">&lt;</button>

Actual result: 

&lt;button data-glide-dir=&quot;&lt;</button>

This breaks glide.js unless we use this workaround (​https://github.com/glidejs/glide/issues/547)

I think this should be allowed as per ​https://html.spec.whatwg.org/multipage/syntax.html#syntax-attributes

Thanks and best regards

Change History (11)

#1 @jernstjernst
2 years ago

Sorry, the test case should read:

<?php
echo wp_kses_post('<button data-glide-dir="<">&lt;</button>')
?>

#2 @jonsurrell
2 years ago

This is certainly incorrect behavior and the HTML you shared is indeed fine. The fundamental problem is that kses, as a system, doesn't really understand HTML.

There are efforts to improve things with the ​HTML API, but it's not entirely ready to replace everything kses does yet.

I'd suggest encoding the attribute value as a workaround, kses shouldn't have a problem understanding this HTML:

<?php
wp_kses_post('<button data-glide-dir="&lt;">&lt;</button>');
// returns '<button data-glide-dir=\"&lt;\">&lt;</button>'

#3 @jonsurrell
12 months ago

  • Version 6.7 → 5.0

​Here's a demo of the behavior.

I've confirmed this behavior as of version 6.3, but I suspect it's been around much longer. I'll set the version arbitrarily to 5.0.

This ticket was mentioned in ​PR #13704 on ​WordPress/wordpress-develop by ​@arkaprabhachowdhury.


11 days ago
#4

  • Keywords has-patch has-unit-tests added

Summary

  • Add regression coverage for Trac #62024, ensuring KSES preserves a literal < in a quoted data-* value.
  • Compare HTML semantics because KSES safely serializes the character as &lt;.

The HTML API parser is already used by wp_kses_hair() in trunk; this covers the original end-to-end case that was not explicitly tested.

Fixes #62024

#5 @arkaprabhachowdhury
7 days ago

A fix for this issue has been raised in (​https://github.com/WordPress/wordpress-develop/pull/13704).

Last edited 7 days ago by arkaprabhachowdhury (previous) (diff)

​@jonsurrell commented on ​PR #13704:


6 days ago
#6

Thanks for the PR.

I'd prefer something like ​https://github.com/WordPress/wordpress-develop/pull/13271 that has potential to fix this category of defect that KSES has today by relying on a parser that correctly handles HTML syntax.

The type of defect in the ticket is caused by trying to manipulate HTML with regular expressions. I don't think more or even better regular expressions are the solution we need here.

​@arkaprabhachowdhury commented on ​PR #13704:


6 days ago
#7

Ah makes sense @sirreal. I will look into it and raise a better fix that uses the parser instead of regex.
Thanks!

​@arkaprabhachowdhury commented on ​PR #13704:


6 days ago
#8

Thanks @sirreal. I updated this to use WP_HTML_Tag_Processor to identify and reserialize attribute values containing a literal < before the existing KSES split.

The change stays focused on this attribute-parsing issue and retains the existing handling for incomplete tokens, comments, blocks, foreign content, and other markup. Regression coverage now includes both single-quoted and double-quoted values.

#9 @dmsnell
6 days ago

  • Milestone Awaiting Review
  • Resolution → duplicate
  • Status new → closed

I’m going to fold this into the work in #66208 by marking it as a duplicate, even though this issue is older. The linked ticket rewrites wp_kses() comprehensively and addresses this issue as a byproduct of replacing the HTML parsing code.

​@dmsnell commented on ​PR #13704:


6 days ago
#10

This should be covered by #13271 which re-implements wp_kses(), but given that we are going to hold around the legacy filters for at least a little while, I think the PR could still be valuable.

That being said, there are a number of issues with the code as written. Please consider HTML text notes, note that there is a discrepancy between calling next_token() and getting attributes, and find examples of the use of lexical_udpates in sub-classes to perform token-level replacement rather than retaining the troublesome PCRE replacement.

​@jonsurrell commented on ​PR #13704:


5 days ago
#11

Sorry @ArkaPrabhaChowdhury, I was unclear. ​https://github.com/WordPress/wordpress-develop/pull/13271 will fix #62024 without the need for any smaller fixes like this. It should make this work obsolete.

Note: See TracTickets for help on using tickets.