diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php index 44828e4..67fdd28 100644 --- a/core/modules/dblog/src/Controller/DbLogController.php +++ b/core/modules/dblog/src/Controller/DbLogController.php @@ -8,8 +8,9 @@ namespace Drupal\dblog\Controller; use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\Unicode; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\String; +use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\Xss; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Database\Connection; @@ -240,6 +241,14 @@ public function eventDetails($event_id) { '#theme' => 'username', '#account' => user_load($dblog->uid), ); + // Validate the event link if it is safe. + if (!SafeMarkup::isSafe($dblog->link)) { + $event_link = Xss::filterAdmin($dblog->link); + } + else { + $event_link = $dblog->link; + } + $rows = array( array( array('data' => $this->t('Type'), 'header' => TRUE), @@ -275,7 +284,7 @@ public function eventDetails($event_id) { ), array( array('data' => $this->t('Operations'), 'header' => TRUE), - $dblog->link, + $event_link, ), ); $build['dblog_table'] = array( @@ -352,7 +361,7 @@ public function formatMessage($row) { else { $message = FALSE; } - return $message; + return ($message) ? Xss::filterAdmin($message) : FALSE; } /** diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php index d6a59ad..28edfaa 100644 --- a/core/modules/dblog/src/Tests/DbLogTest.php +++ b/core/modules/dblog/src/Tests/DbLogTest.php @@ -7,9 +7,11 @@ namespace Drupal\dblog\Tests; +use Drupal\Component\Utility\String; use Drupal\Component\Utility\Unicode; use Drupal\Component\Utility\Xss; use Drupal\Core\Logger\RfcLogLevel; +use Drupal\Core\Url; use Drupal\dblog\Controller\DbLogController; use Drupal\simpletest\WebTestBase; @@ -71,6 +73,8 @@ function testDbLog() { $this->verifyEvents(); $this->verifyReports(); $this->verifyBreadcrumbs(); + $this->verifyLinkEscaping(); + $this->verifyMessageEscaping(); // Verify the overview table sorting. $orders = array('Date', 'Type', 'User'); $sorts = array('asc', 'desc'); @@ -247,6 +251,82 @@ public function verifySort($sort = 'asc', $order = 'Date') { } /** + * Tests the escaping of links in the operation row of a database log detail + * page. + */ + private function verifyLinkEscaping() { + $link = \Drupal::l('View', Url::fromRoute('entity.node.canonical', array('node' => 1))); + $message = 'Log entry added to do the verifyLinkEscaping test.'; + $this->generateLogEntries(1, array( + 'message' => $message, + 'link' => $link, + )); + + $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1); + $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField()); + + // Check if the link exists (unescaped). + $this->assertRaw($link); + + // Check for XSS filtering. + $js_txt = 'This should not pop up!'; + $js = ''; + $this->generateLogEntries(1, array( + 'message' => $message, + 'link' => $link . $js, + )); + + $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1); + $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField()); + + // Check if the link exists (unescaped). + $this->assertRaw($link); + + // Check if javascript was escaped. + $this->assertNoRaw($js, 'Detail view: javascript in link is blocked'); + $this->assertRaw($js_txt, 'Detail view: javascript text exists'); + } + + /** + * Test the escaping of message in the operation row of a database log detail + * page. + */ + private function verifyMessageEscaping() { + $link = \Drupal::l('View', Url::fromRoute('entity.node.canonical', array('node' => 1))); + $message = String::format('%message', array( + '%message' => 'Log entry added to do the verifyMessageEscaping test.', + )); + $this->generateLogEntries(1, array( + 'message' => $message, + 'link' => $link, + )); + + $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1); + $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField()); + + // Check if the link exists (unescaped). + $this->assertRaw($message); + + // Check for XSS filtering. + $js_txt = 'This should not pop up!'; + $js = ''; + $this->generateLogEntries(1, array( + 'message' => $message . $js, + 'link' => $link, + )); + + $result = db_query_range('SELECT wid FROM {watchdog} ORDER BY wid DESC', 0, 1); + $this->drupalGet('admin/reports/dblog/event/' . $result->fetchField()); + + // Check if the link exists (unescaped). + $this->assertRaw($message); + + // Check if javascript was escaped. + $this->assertNoRaw($js, 'Detail view: javascript in message is blocked'); + $this->assertRaw($js_txt, 'Detail view: javascript text exists '); + } + + /** * Generates and then verifies some user events. */ private function doUser() {