Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Part of #2297711: Fix HTML escaping due to Twig autoescape. See that issue for details.
Problem/Motivation
The "Operations" link at admin/reports/dblog/event/[ID]
is double-escaped for every log message.
Before:
After:
From DbLogController::eventDetails():
array(
array('data' => $this->t('Hostname'), 'header' => TRUE),
String::checkPlain($dblog->hostname),
),
array(
array('data' => $this->t('Operations'), 'header' => TRUE),
$dblog->link,
),
);
$build['dblog_table'] = array(
'#type' => 'table',
'#rows' => $rows,
'#attributes' => array('class' => array('dblog-event')),
'#attached' => array(
'library' => array('dblog/drupal.dblog'),
),
);
Proposed resolution
Fix it.
Remaining tasks
Commit it. :-)
Task | Novice task? | Contributor instructions | Complete? |
---|
Beta phase evaluation
Issue category | Bug because it fixes double escaping by Twig which results in html displayed as plain text. |
---|---|
Issue priority | Major because it is a user facing text display |
Unfrozen changes | Unfrozen because it only changes markup. |
Prioritized changes | The main goal of this issue is usability. |
Disruption | Not disruptive. |
Comment | File | Size | Author |
---|---|---|---|
#132 | interdiff-118-132.txt | 1.4 KB | zaporylie |
#132 | fix_double_escaping_due-2345779-132.patch | 5.33 KB | zaporylie |
#130 | 2345779-127.patch | 6.1 KB | zaporylie |
#128 | interdiff.txt | 1.11 KB | Noe_ |
#127 | 2345779-127.patch | 6.1 KB | Noe_ |
Comments
Comment #1
xjmComment #2
Yaron Tal CreditAttribution: Yaron Tal commentedComment #3
Yaron Tal CreditAttribution: Yaron Tal commentedAttached a test-only patch and a fix+test patch.
Comment #5
Yaron Tal CreditAttribution: Yaron Tal commentedTest-only patch failed, so that looks good.
Comment #6
clemens.tolboomComment #7
Yaron Tal CreditAttribution: Yaron Tal commentedLooks good, maybe make the generateLogEntries() easier to read by having a $default log message and allow the caller to override options at call-time? Especially in the case of verifyLinkEscaping() where you only need to override the link paramater.
Comment #8
Yaron Tal CreditAttribution: Yaron Tal commentedNew patch. Replaced the hardcoded link by a call to l(), gave the generateLogEntries() function an $options array paramater and updated all calls to use the new format.
Comment #9
m.ioannidis CreditAttribution: m.ioannidis commentedI'm currently reviewing it.
Hope everything works fine.
Comment #10
m.ioannidis CreditAttribution: m.ioannidis commentedIt's been tested and seems legit!
The patch did solved the problem.
Comment #12
m.ioannidis CreditAttribution: m.ioannidis commentedI'm on reroll now since the patch seems outdated at the moment.
Comment #13
m.ioannidis CreditAttribution: m.ioannidis commentedFixed a minor coding standard issue in the patch.
Comment #15
mradcliffeThe l() function was deprecated recently and those references need to be changed.
Comment #16
gngn CreditAttribution: gngn commentedIn #13 you changed in function eventDetails() from
$dblog->link
to
SafeMarkup::set($dblog->link)
So basically you say everything someone passes as link is safe.
When I call it with something like
<a href="http://drupal.org">drupal</a><script>alert("hi there");</script>
the Javascript will get passed unchanged to the page and execute (see attached image).
In overview() we use
Xss::filter($dblog->link)
so I think it's better to apply it here too.
One could argue that a module should make sure, what it passes into the Logger, but I do not think so.
Anyway we should either use SafeMarkup or Xss::filter in both eventDetails() and overview().
Working on a patch...
Comment #17
aneek CreditAttribution: aneek commentedHello Guys,
I just had a go on the patch. Here is what I modified.
SafeMarkup::set()
I've added a check to validate if the event URL is safe or not withSafeMarkup::isSafe()
. If it's not that safe then usedXss::filterAdmin()
(since its an admin page) to sanitize it properly.l()
function. This should be_l()
l()
function is deprecated so I've used the URL generation APIComment #18
aneek CreditAttribution: aneek commentedComment #19
mradcliffeI like this use of SafeMarkup. NIce. +1.
It's a private function, but maybe a core developer would want to know what the options are.
Maybe:
Comment #21
aneek CreditAttribution: aneek commentedTest failed but the code seems to work properly in local installations. However, have to check the test cases.
Comment #22
aneek CreditAttribution: aneek commentedSome issues fixed with
SafeMarkup
checks. Also, when usedUrl::fromUri($dblog->referer)
, if the value$dblog->referer
is not set then an error was triggering. Like,So added an empty check.
Uploading a new patch and marking for review. Keeping fingers crossed. :-)
Comment #23
aneek CreditAttribution: aneek commentedComment #24
marcus7777 CreditAttribution: marcus7777 commentedreviewing
Comment #25
marcus7777 CreditAttribution: marcus7777 commentedapplied patch 22
The code make sense and is working as intended.
before
after
Comment #26
marcus7777 CreditAttribution: marcus7777 commentedupdating image
Comment #27
marcus7777 CreditAttribution: marcus7777 commentedComment #28
marcus7777 CreditAttribution: marcus7777 commentedComment #29
marcus7777 CreditAttribution: marcus7777 commentedComment #30
mradcliffeWe have tests and we have a patch.
Comment #34
aneek CreditAttribution: aneek commentedWhat the?? The patch was passed initially and now how its failing? Any ideas?
Comment #35
mradcliffeThe patch no longer applies to HEAD. The next step is to re-roll the patch after fetching and merging the latest changes from HEAD - https://www.drupal.org/patch/reroll
Comment #36
tim.plunkettThe patch no longer applies cleanly to the codebase. See https://www.drupal.org/patch/reroll for instructions on rerolling it.
Comment #37
aneek CreditAttribution: aneek commentedThanks guys.
I'll have a look at this tonight.
Comment #38
gngn CreditAttribution: gngn commentedI rerolled the patch.
I think we should not only test for displaying of the link,
but also for checking XSS, so I added tests for that.
Other than that, I also sorted the use-statements alphabetically.
Comment #39
gngn CreditAttribution: gngn commentedSorry, there we're some misplaced spaces left.
Other than that #39 is the same as #38.
Comment #40
gngn CreditAttribution: gngn commentedAlso forgot to mark it "needs review"... ;)
Comment #41
aneek CreditAttribution: aneek commentedThanks @gngn for this patch. Lets make it RTBC.
Comment #42
vurt CreditAttribution: vurt commentedI tested #39 and it works as expected.
Comment #43
vurt CreditAttribution: vurt commentedI think I accidentally changed the status to needs work... setting it back to needs review...
Comment #44
joelpittetWhy is there an API change here? Is this necessary or out of scope of this issue?
I know it's easy to fall victim to cleaning up all of the files, but it can muddy the waters for a reviewer to try to determine what parts of the code were fixing the the problem and which parts are just nice to have clean-ups. And also provide bikeshed fodder. So be warned:P
Comment #45
gngn CreditAttribution: gngn commentedThe parameters of generateLogEntries() were changed because we needed to set not only type (aka channel) and severity, but also the link.
The new version allows to change every parameter by passing an array of a options (and provides defaults).
We could have added just one new parameter:
but I think it's better to allow overriding all parameters.
This way if we need more settings in future test cases, we do not need to change the API again and again.
Comment #46
tim.plunkettThis isn't an API change either way. That is a *private* method of a test. It cannot be overridden by subclasses.
Comment #47
joelpittetProbably shouldn't say API change there, meant function definition.
Trying to prevent scope creep, that's all. Anyways seems like you have it sorted and thought out. Carry on...
Comment #48
jibranComment #49
subhojit777Comment #52
subhojit777The patch in #39 is working alright. It just needed reroll.
Comment #54
Yaron Tal CreditAttribution: Yaron Tal commentedThe change to the generateLogEntries function signature was removed between #38 and #39.
So a new patch should be created, based on #52, but with this change added:
- private function generateLogEntries($count, $type = 'custom', $severity = WATCHDOG_NOTICE) {
+ private function generateLogEntries($count, $options = array()) {
Maybe someone should check if other stuff also went missing by doing a diff between the patches.
Comment #55
subhojit777Comment #56
subhojit777@Yaron Tal I did not found much difference between #38 and #39. Interdiff attached.
Comment #57
subhojit777I hope this one will pass the test.
Comment #58
subhojit777It would be good if we do not use l() function, it is deprecated.
Comment #59
subhojit777This patch uses \Drupal::l()
Comment #60
subhojit777Comment #61
tim.plunkettThese changes are wrong, $this->l() is preferred over \Drupal::l()
I'd do
$logger = $this->container->get('logger.dblog');
outside this code block. The first one is in a loop, it's a waste of get() calls.Please use protected (I know the other method uses private, but fixing that is out of scope here)
Comment #62
subhojit777Comment #63
subhojit777@tim.plunkett Could you please explain why the l() function changes are wrong. I see that l() has been deprecated in 8 (Deprecated)
Comment #64
joelpittetI think I can answer that. By using the internal method instead of the global static method the object is easier to unit test.
Because the object is self-contained with its dependencies injected.
The same applies for the \Drupal::t() method vs $this->t()
Does that help? I'm sure Tim can elaborate if I missed something or needs further clarification.
Comment #65
subhojit777Thanks that helps :) And here is the patch with suggestions from Tim in #61
Comment #66
subhojit777Comment #67
LinL CreditAttribution: LinL commentedPatch no longer applies, tagging for reroll.
Comment #68
rpayanmComment #69
gvsoRTBC +1 for #68
Comment #70
ravi.khetri CreditAttribution: ravi.khetri commentedRe-rolled.
Comment #71
ravi.khetri CreditAttribution: ravi.khetri commentedRe-rolled.
Comment #72
ravi.khetri CreditAttribution: ravi.khetri commentedComment #73
subhojit777Its not working anymore
Comment #74
gvso@subhojit777, I'm not able to reproduce what you got, actually the double-scaping just occurs in the operation detail
Comment #75
subhojit777@gvso I was installing some modules (xmlsitemap, extlink) and they were not installing cleanly in my Drupal 8 instance. Message details is double escaped, I think we should fix it in this issue only.
Comment #76
subhojit777Using the same logic as used in event link.
Comment #77
gvsoSending to testbots
Comment #79
manningpete CreditAttribution: manningpete commentedI could apply the patch, so no reroll is needed.
Comment #81
subhojit777Using the same test logic as used for link.
Comment #83
idebr CreditAttribution: idebr commentedAttached patch includes the patch from #2409881-1: Exception log messages are double-escaped when viewing a single entry to fix the failing test.
Comment #84
idebr CreditAttribution: idebr commentedComment #85
Sachini CreditAttribution: Sachini commentedRe rolling patch to apply cleanly at ce199a1 with improvements for coding style.
Comment #86
subhojit777If you are using multi-line array style, the closing braces should appear in next line.
Comment #87
subhojit777Tests have been added, hence removing the tag
Comment #88
subhojit777Comment #89
idebr CreditAttribution: idebr commentedChanges look good! I have added a test-only version to verify the tests failures.
Comment #91
idebr CreditAttribution: idebr commentedThe patch fixes the display and includes tests to make sure the markup is escaped. Looks RTBC to me :)
I have updated the issue summary with a beta evaluation to reflect this is a bugfix.
Comment #94
idebr CreditAttribution: idebr commentedTestbot hickup? I didn't have an opportunity to have a look at the test report, but since it comes back green I take it everything is all good.
Comment #95
alexpott^^ is the documentation from SafeMarkup::set(). I think we need another solution here.
Comment #96
idebr CreditAttribution: idebr commentedI suppose there is no need to call that function there, since the markup is already considered safe.
Comment #98
subhojit777Patch looks good, and it fixes the problem. Patch includes all changes asked in #95. Tests included. Marking it as RTBC.
Comment #99
alexpottThere is a tonne of unrelated change in this patch
Why the change to ?
Why?
unrelated
Unrelated
Why are we changing this?
We're always filtering in the
formatMessage()
so this will always be safe.Comment #100
SebCorbin CreditAttribution: SebCorbin commentedRemoved unrelated changes as per #99
Comment #102
scor CreditAttribution: scor commentedWe still need to keep the fix from #2409881: Exception log messages are double-escaped when viewing a single entry. I've also removed a couple of unrelated changes.
Credit should be give to @joelpittet in the commit.
Comment #104
subhojit777Comment #105
subhojit777From comment #99, we infact need some changes to fix the bug.
This issue is to fix html escape bug in dblog events (messages, links). The previous
generateLogEntries()
did not covered custom dblog message and links. Therefore we need this change #99.5. And due to this we also have to changetestFilter()
(as mentioned in last part of #99.4)I hope other queries in #99 has been covered.
Comment #107
adhoc CreditAttribution: adhoc commentedComments in #99 have been addressed,
There are tests in the patch and they pass,
Fixes the escaping issue.
Comment #108
alexpottCan use
$event_link = SafeMarkup::checkAdminXss($dblog->link);
here instead of all of this. Perhaps can just remove the$event_link
variable completely.The new $options parameter should have documentation about the defaults and possible options.
This looks a bit painful. Is the
if ($count > 1) {
actually necessary?Comment #109
singularoTook the suggestions from @alexpott and made the changes to the patch.
Re-tested, appears to fix the problem, and it simpler.
The descriptions in the options array might need some tweaking.
My first issue update for core, let me know if I've made any mistakes please.
Comment #110
pingers CreditAttribution: pingers commentedUse sentences - missing period.
Comment #111
singularoAdded periods to sentences in options section
Comment #113
asheresque CreditAttribution: asheresque commentedI have confirmed that the patch applies cleanly on head and that it resolves the problem, and also that it follows coding standards.
Comment #114
alexpottThis issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 630edf8 and pushed to 8.0.x. Thanks!
Comment #116
alexpottDone some more thinking about this change. I don't think it is correct. This is preventing someone from writing code like
$logger->notice('<script>alert('blah')</script>');
- however this is does not need to be defended against. All user input should be passed to the message through the variables with the correct escaping strategy.Comment #118
singularoXss filtering of the message and testing of same removed in updated patch & interdiff attached.
Comment #119
alexpottThis is no longer needed.
Comment #120
subhojit777Comment #121
subhojit777Comment #122
pfrenssenMarked #2462133: Link in log message should not be escaped as a duplicate of this issue.
Comment #123
Noe_ CreditAttribution: Noe_ commentedI could apply the patch, so no reroll is needed.
I removed two private functions because they were no longer called. Tested it again, still passed.
So now ready to be commited.
Comment #124
idebr CreditAttribution: idebr commented@Noe_ Thanks for working on this patch! If you make any changes to a patch, please set the status to 'Needs review' so it can be reviewed by fellow developers. More information on issue status can be found in the Issue queue handbook: https://www.drupal.org/node/156119.
Comment #125
Noe_ CreditAttribution: Noe_ commentedIt seems the private functions seem to be called by the Testbot, so here is the new patch.
Comment #126
subhojit777@Noe_ @alexpott has asked to removed
verifyMessageEscaping()
in #119. Please correct the patch.Comment #127
Noe_ CreditAttribution: Noe_ commentedThe
verifyMessageEscaping()
function is the only one that is removed now as @alexpott pointed out in #119Comment #128
Noe_ CreditAttribution: Noe_ commentedForgot the interdiff.
Comment #130
zaporylieThat's another upload of #127 since testbot had some obvious problem last week.
Comment #131
zaporylieOk, just realized that you removed testDbLog() to get green test results - that's cool ;) but I guess it's not something we can do. I will work on it but will take #118 as a base since that was last patch with testDbLog()
Comment #132
zaporylieHere is a patch based on #118 and suggestion from #119 which passes local tests. Let's try it against DrupalCI.
Comment #133
zaporylieOk
Since last patch is based on RTBC, and nothing, but Alex suggestion, were added, I'm bumping it back to RTBC
Comment #134
alexpottCommitted 4b1714a and pushed to 8.0.x. Thanks!
Thanks for adding the beta evaluation.
Fixed unused use.