Opened 11 months ago
Last modified 11 months 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: |
|
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 $allowedtagsfor 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_htmlcapability), then the<img>is not removed. (as expected)
Change History (10)
#2
@
11 months 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
inithook instead ofpre_comment_on_postresolved 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
@
11 months 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
@
11 months 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
@
11 months ago
Replying to turbodb:
Using the
wp_kses_allowed_htmlfilter 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
@
11 months ago
Replying to siliconforks:
Replying to turbodb:
Using the
wp_kses_allowed_htmlfilter 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_contenthook is not the same thing as thepre_comment_on_posthook. I believe thatpre_comment_contentis 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
@
11 months 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
@
11 months 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
@
11 months 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
inithook instead ofpre_comment_on_postresolved 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:
function add_post_comment_html_tags() { global $allowedtags; $new_tags = array( 'img' => array( 'src' => true, 'class' => true, 'style' => true, 'alt' => true, ), ); $allowedtags = array_merge( $allowedtags, $new_tags ); } add_action( 'init', 'add_post_comment_html_tags' );