Skip to content

Error sanitizing with --> in <script> tag #153

Closed
@jvbrandis

Description

@jvbrandis

There seems to be a bug in the sanitizer when sanitizing script tags which contains a HTML comment end tag.

We generate a JSON blob which is inserted into a <script> tag of type application/json, and our HTML policy allows script tags of this type, with text content. However, in certain cases, the JSON contains a value string which looks like a HTML comment end, e.g. "cause --> effect".
(see test case scriptTagWithCommentBlockContainingHtmlCommentEnd)

When this happens, the sanitizer completely drops the entire text contents of the script tag.
This happens regardless of whether the text contents are surrounded by a HTML comment block
(see test case scriptTagWithoutCommentBlockContainingHtmlCommentEnd).
There is also no event fired at the HtmlChangeListener when this happens.

Escaping the JSON string by escaping the right angular solves the problem, however this is no longer valid JSON. (see scriptTagWithCommentBlockContainingEscapedHtmlCommentEnd).

The following code snippet highlights the problem:

package test;

import org.junit.Test;
import org.owasp.html.HtmlPolicyBuilder;
import org.owasp.html.PolicyFactory;

import java.io.IOException;
import java.util.HashSet;

import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;

public class OwaspSanitationTest {


  @Test
  public void scriptTagWithCommentBlockContainingHtmlCommentEnd() throws IOException {
    String html = "<script type=\"application/json\">\n" +
            "<!--\n" +
            "{\"field\":\"-->\"}\n" +
            "// -->\n" +
            "</script>";
    assertEquals(html, createHtmlSanitizer().sanitize(html));
  }
  @Test
  public void scriptTagWithCommentBlockContainingEscapedHtmlCommentEnd() throws IOException {
    String html = "<script type=\"application/json\">\n" +
            "<!--\n" +
            "{\"field\":\"--\\>\"}\n" +
            "// -->\n" +
            "</script>";
    assertEquals(html, createHtmlSanitizer().sanitize(html));
  }

  @Test
  public void scriptTagWithoutCommentBlockContainingHtmlCommentEnd() throws IOException {
    String html = "<script type=\"application/json\">\n" +
            "{\"field\":\"-->\"}\n" +
            "</script>";
    assertEquals(html, createHtmlSanitizer().sanitize(html));
  }

  private PolicyFactory createHtmlSanitizer() {
    return new HtmlPolicyBuilder()
            //allow scripts of type application/json
            .allowElements((elementName, attrs) -> {
              int typeIndex = attrs.indexOf("type");
              if (typeIndex < 0 || attrs.size() < typeIndex + 1 || !attrs.get(typeIndex + 1).equalsIgnoreCase("application/json"))
                return null;
              return elementName;
            }, "script")
            //allow contents in this script tag
            .allowTextIn("script")
            //keep type attribute in application/json script tag
            .allowAttributes("type").matching(true, new HashSet<>(singletonList("application/json"))).onElements("script")
            .toFactory();
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions