Problem

The rewrite for "Content: Path" says "You may include HTML or Twig." but then it escapes any HTML.

Steps

  1. Create view to show fields for content
  2. Add a "Content: Path" field
  3. Rewrite the field and add HTML
  4. The rewrite incorrectly escapes the HTML

Comments

ccmorris created an issue. See original summary.

ccmorris’s picture

Possible duplicate of #2584655: Views field "Global > Custom Text" incorrectly escapes HTML, though token replacement is not necessary to repeat the problem. There is a workaround for the bug there as well.

ccmorris’s picture

Title: HTML is escaped in Views field rewrite for Custom text and Content Path » Views field rewrite for "Content: Path" incorrectly escapes HTML
Priority: Normal » Major
Issue summary: View changes

#2584655: Views field "Global > Custom Text" incorrectly escapes HTML covers the incorrect escaping using "Custom text" field. Fixing that issue would likely solve the escaping for the "Content: Path" rewrite. I have changed the title of this issue in case it does not.

Priority changed to Major since this is a regression.

ccmorris’s picture

ccmorris’s picture

Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new1.05 KB

I decided to try to tackle this myself. I have attached a patch that needs review. Is it safe to use ViewsRenderPipelineMarkup on the alias URL after a Xss::filterAdmin?

This should probably have tests too.

dawehner’s picture

Status: Needs review » Needs work
+++ b/core/modules/node/src/Plugin/views/field/Path.php
@@ -68,7 +70,8 @@ public function query() {
-    return \Drupal::url('entity.node.canonical', ['node' => $nid], ['absolute' => $this->options['absolute']]);
+    $url = \Drupal::url('entity.node.canonical', ['node' => $nid], ['absolute' => $this->options['absolute']]);
+    return ViewsRenderPipelineMarkup::create(Xss::filterAdmin($url));
   }

IMHO the right thing to do would be to return a simple render eoement with just ['#markup']
ViewsRenderPipelineMarkup is really more about internals of views.

rakesh.gectcr’s picture

Assigned: Unassigned » rakesh.gectcr
rakesh.gectcr’s picture

Assigned: rakesh.gectcr » Unassigned
Status: Needs work » Needs review
StatusFileSize
new689 bytes
new1.05 KB

@dawehner,

++, patch changed according to above comment. and tested manually.

dawehner’s picture

Status: Needs review » Needs work

We need automated tests, sorry

cilefen’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new7.9 KB
new7.2 KB
new7.86 KB

The last submitted patch, 10: views_field_rewrite_for-2594917-10-TEST.patch, failed testing.

mikeker’s picture

StatusFileSize
new544 bytes
new7.82 KB
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_path_plugin.yml
@@ -0,0 +1,183 @@
+uuid: fccbe0a6-be65-4789-8100-dacc4ddd3f31

Removed UUID from the added test view.

mikeker’s picture

Status: Needs review » Reviewed & tested by the community

Since my change was very minor I'm going to RTBC this. The code change looks good and relies on Twig's auto-escaping -- always a good thing.

Thank you, @cilefen, for the tests!

The last submitted patch, 10: views_field_rewrite_for-2594917-10-TEST.patch, failed testing.

mikeker’s picture

Hiding test-only patches...

dawehner’s picture

+1 for this fix. We applied similar strategies in other areas.

catch’s picture

Status: Reviewed & tested by the community » Needs work

I was confused why this works reading the patch. What's getting escaped is not the canonical URL for the node, but the altered text - so I could not figure out why making the URL #markup would affect anything.

Reading through, it looks like it will be this hunk in FieldPluginBase::renderText():

    if ($value_is_safe) {
      $value = ViewsRenderPipelineMarkup::create($value);
    }

So the problem is that the 'safeness' of the rewritten text is based on the 'safeness' of the original text.

To me that looks like a much deeper issue with SafeMarkup and field rewrites, and at a minimum we should look at a follow-up + comments here explaining why it works like this.

ccmorris’s picture

So the problem is that the 'safeness' of the rewritten text is based on the 'safeness' of the original text.

I see what you mean. The 'safeness' of the rewrite should be independent from the 'safeness' of the original value.

In FieldPluginBase::renderText(), the returned text is autoescaped by Twig if the original text is unsafe. Could we escape unsafe text before rewriting, rather than after?

mikeker’s picture

Status: Needs work » Needs review

From #17:

I was confused why this works reading the patch. What's getting escaped is not the canonical URL for the node, but the altered text - so I could not figure out why making the URL #markup would affect anything.

At core/modules/views/src/Plugin/views/field/FieldPluginBase.php:1140 the render() method is called and, if a render array is returned it's converted to a Render\Markup object. When FieldPluginBase::renderText is later called, $value_is_safe is (correctly) set to true as viewsTokenReplace() will return an XSS admin filtered string.

If Path::render() returns just a URL string, then $value_is_safe ends up as false. Perhaps incorrectly? We could mark the return from Path::render() as safe, but I thought we were trying to get away from that...

mikeker’s picture

Issue tags: +Needs followup

Though this does raise a point: renderText() does an awful lot of string replacements and whatnot. All of these need to be (at a minimum) Xss::filterAdmin()'ed and by packing them all in one long method with a comment at the top seems like a security issue waiting to happen.

But that cleanup should happen in a followup issue...

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mikeker’s picture

Possibly related issue.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs followup

Filed this followup: #2760143: Refactor views rewrite to be a) sane and b) secure


+++ b/core/modules/node/src/Tests/Views/PathPluginTest.php
@@ -0,0 +1,83 @@
+/**
+ * @file
+ * Contains \Drupal\node\Tests\Views\RowPluginTest.
+ */

Nitpick on commit: Remove the @file header.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 8fb4440373a148a04f631090fc924ba74d44362e to 8.2.x and 61301b5 to 8.1.x. Thanks!

And yes views rewriting and safeness is hard and complex.

Fixes on commit:

diff --git a/core/modules/node/src/Tests/Views/PathPluginTest.php b/core/modules/node/src/Tests/Views/PathPluginTest.php
index e48cb87..1ee6272 100644
--- a/core/modules/node/src/Tests/Views/PathPluginTest.php
+++ b/core/modules/node/src/Tests/Views/PathPluginTest.php
@@ -1,14 +1,8 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\node\Tests\Views\RowPluginTest.
- */
-
 namespace Drupal\node\Tests\Views;
 
 use Drupal\views\Views;
-use Drupal\node\Entity\Node;
 
 /**
  * Tests the node row plugin.

  • alexpott committed 8fb4440 on 8.2.x
    Issue #2594917 by cilefen, mikeker, rakesh.gectcr, ccmorris, dawehener:...

  • alexpott committed 61301b5 on 8.1.x
    Issue #2594917 by cilefen, mikeker, rakesh.gectcr, ccmorris, dawehener:...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.