Opened 7 weeks ago
Last modified 7 weeks ago
#62644 reopened defect (bug)
Editing comments as an admin, in the Admin UI, filters the HTML elements of the comment as though the edit was done by the original author.
Reported by: | turbodb | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 6.7.1 |
Component: | Comments | Keywords: | |
Focuses: | Cc: |
Description
Problem Description:
I know that comments don’t allow img elements by default (for unregistered users). For privacy/spam reasons, of course. On my site, I manually moderate all comments, so this is less of an issue for me, and there are times when it is important for people (not signed-in users) to be able to link to images.
Repro Steps:
- Add the following code to
functions.php
, which will allow non-registered users to include the<img>
element in comment contents.
function add_post_comment_html_tags( $commentdata ) { global $allowedtags; $new_tags = [ 'img'=> [ 'src'=> true, 'class'=> true, 'style'=> true, 'alt'=> true ] ]; $allowedtags = array_merge( $allowedtags, $new_tags ); } add_action('pre_comment_on_post', 'add_post_comment_html_tags' );
- As a non-registered user, leave a comment on a post, utilizing the
<img>
HTML element to include an image.
===> Note that the image is successfully allowed into the comment.
- Log in to the site as an administrator and navigate to the Comments page in Admin UI.
- Edit (or Quick Edit) the comment, and change the contents slightly, but leave the
<img>
element alone.
- Save your changes.
Result:
Once the comment is saved by the admin, the <img>
element is removed entirely, even though the administrator can create comments - either in the admin UI or frontend - that contain <img>
elements.
This happens because the comment edit is committed as / impersonates the original comment author on save, and is not executed as the current editor (administrator) in the Admin UI. Further, because the comment already exists, the pre_comment_on_post
action is not called, so <img>
is not added to the global $allowedtags
.
Expect:
I would expect one of two things:
- That edits to comments in the admin UI are performed *as the current user editing the comment* instead of as the original comment author.
- That there be a way to modify the
global $allowedtags
for comment edits, in the same way that there is for comment creation.
Notes:
- I originally brought this up here, for a bit more context: https://wordpress.org/support/topic/how-to-prevent-editing-of-comments-as-admin-from-stripping-images/
- There may already be a filter/hook that serves this purpose, but I couldn't find one in the docs. I tried
comment_save_pre
, which did not work successfully. - If the administrator edits a comment that was originally created by an administrator (or any user with the
unfiltered_html
capability), then the<img>
is not removed. (as expected)
Change History (10)
#2
@
7 weeks ago
Hi @yogeshbhutkar,
Thanks for the quick response, and the workaround suggestions. A couple thoughts on your suggestions:
- I agree with your suggestion of using a plugin rather than functions.php, and in fact, that is what I'm doing. I was trying to provide the simplest repro steps in the bug report, and functions.php seemed a lighter weight repro than creating a plugin.
- I know that I can use
init
, but that's a much heavier weight (riskier / larger surface area) solution than the one I'm looking for (to your point about looking for a "safer" solution). There are two reasons it is heavy-handed:- it runs every single page load, rather than only when comments are in play.
- it adds/allows <img> in all cases, opening up a larger surface area than allowing it only for the case (comments) for which I want it to be allowed.
And, a clarification:
You stated:
...using the
init
hook instead ofpre_comment_on_post
resolved the problem for me.
To be clear - the pre_comment_on_post
works perfectly when the comment is initially created, which is the only time I would expect it to run, since it is "pre" the comment being added on a post.
The time when it doesn't run - and I was suggesting that another hook should exist for this case - is when a comment is being edited in the Admin UI. I'd expect a hook such as pre_comment_edit
or something of that nature.
Net net:
It seems to me that if there is a hook for "before comment creation," there should be a matching hook for "before comment edit," since, otherwise, there's no way to ensure that operations done during (and scoped to) creation are maintained during (and still scoped to) comment edits.
#3
@
7 weeks ago
Did you try using the wp_kses_allowed_html
filter, as suggested in the forum topic?
Example:
<?php function my_wp_kses_allowed_html_for_comments( $html, $context ) { if ( 'pre_comment_content' === $context ) { $html['img'] = [ 'src'=> true, 'class'=> true, 'style'=> true, 'alt'=> true ]; } return $html; } add_filter( 'wp_kses_allowed_html', 'my_wp_kses_allowed_html_for_comments', 10, 2 );
#4
follow-up:
↓ 5
@
7 weeks ago
Thanks for the suggestion @siliconforks.
Using the wp_kses_allowed_html
filter might work, but in your example you've limited it to the 'pre_comment_content'
, which as I mentioned in the original bug, already works correctly using the hook of the same name.
Without that context limitation, using wp_kses_allowed_html
has the same issue I've raised as using the init
hook - namely that it's a much larger scope and opens up a much larger area than the targetted use of <img>
that I'm aiming to allow here, which is only in comments.
By using wp_kses_allowed_html
- unless there's a $context
for editing comments, in which case, I should be able to use the specific hook for that $context
- I would be allowing <img>
everywhere that HTML is filtered,
#5
in reply to:
↑ 4
;
follow-up:
↓ 6
@
7 weeks ago
Replying to turbodb:
Using the
wp_kses_allowed_html
filter might work, but in your example you've limited it to the'pre_comment_content'
, which as I mentioned in the original bug, already works correctly using the hook of the same name.
I'm not sure what you mean here? The pre_comment_content
hook is not the same thing as the pre_comment_on_post
hook. I believe that pre_comment_content
is used for both posting new comments and editing existing comments.
#6
in reply to:
↑ 5
@
7 weeks ago
Replying to siliconforks:
Replying to turbodb:
Using the
wp_kses_allowed_html
filter might work, but in your example you've limited it to the'pre_comment_content'
, which as I mentioned in the original bug, already works correctly using the hook of the same name.
I'm not sure what you mean here? The
pre_comment_content
hook is not the same thing as thepre_comment_on_post
hook. I believe thatpre_comment_content
is used for both posting new comments and editing existing comments.
Ahh, yep, I was reading too quickly. Let me give that a shot and I'll report back. Is there somewhere I can find the list of valid $context values? There's not much indication of what those are on https://developer.wordpress.org/reference/functions/wp_kses_allowed_html/
#7
@
7 weeks ago
This did work, @siliconforks.
Should I be using this methodology for comment creation as well? If so, a pointer to the $context to use would be helpful.
Thanks.
#8
@
7 weeks ago
The $context value could be basically anything (including custom values used by plugins, etc.). For comments I think you only need to worry about the pre_comment_content
context as I believe this is used for both posting comments on the front-end of the site and editing comments in the admin section.
This is triggered by the pre_comment_content
filter here, which will call the function wp_filter_kses
, which sets the context to the value of current_filter()
here - hence the context is named the same as the filter, pre_comment_content
.
#9
@
7 weeks ago
- Resolution set to invalid
- Status changed from new to closed
Perfect, thanks.
This still seems like a strange misalignment between comment creation and editing (pre_comment_on_post vs. nothing for pre comment edit), but there clearly is a workaround that is scoped to comment content, so from that perspective, I could understand this being resolved as Won't Fix.
Hi @turbodb,
Thank you for raising the ticket. I reviewed the issue described, and using the
init
hook instead ofpre_comment_on_post
resolved the problem for me.That said, I wouldn’t consider the current approach the safest solution. A more robust approach would involve ensuring proper sanitization and escaping throughout the code. Additionally, creating a dedicated plugin, if one doesn’t already exist, would be a better practice, as changes made to the functions.php file risk being overwritten during updates.
Final code: