CVE-2021-22540 (Other, published 2021-04-22T15:15Z)
Description: value: Bad validation logic in the Dart SDK versions prior to 2.12.3 allow an attacker to use an XSS attack via DOM clobbering. The validation logic in dart:html for creating DOM nodes from text did not sanitize properly when it came across template tags.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/dart-lang/sdk
Files changed:
sdk/lib/html/dart2js/html_dart2js.dart
tests/lib/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
tests/lib_2/html/node_validator_important_if_you_suppress_make_the_bug_critical_test.dart
tools/dom/src/Validators.dart
Commit message: [dart:html] Fix sanitization for HTML templates

Bug: b/143778164

Resolves an issue where sanitization wasn't properly handled
when templates were involved.

Change-Id: Ic8f6f28036e18981eb934c2b39c2c0cd4e6f1a96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195056
Reviewed-by: Sigmund Cherem <sigmund@google.com>


Vulnerable code:
  /// Did we modify the tree by removing anything.
  bool modifiedTree = false;
    modifiedTree = false;
    walk(node, null);
    while (modifiedTree) {
      modifiedTree = false;
    }
    modifiedTree = true;
  /// Did we modify the tree by removing anything.
  bool modifiedTree = false;
    modifiedTree = false;
    walk(node, null);
    while (modifiedTree) {
      modifiedTree = false;
    }
    modifiedTree = true;

Fixed code:
  /// Number of tree modifications this instance has made.
  int numTreeModifications = 0;
    // Walk the tree until no new modifications are added to the tree.
    var previousTreeModifications;
    do {
      previousTreeModifications = numTreeModifications;
    } while (previousTreeModifications != numTreeModifications);
    numTreeModifications++;
    // Walking templates triggers a recursive sanitization call, which shouldn't
    // invalidate the information collected from the previous visit of the later
    // nodes in the walk.
    testHtml(
        'DOM clobbering with recursive sanitize call using templates',
        validator,
        "<form><div>"
            "<input id=childNodes />"
            "<template></template>"
            "<input id=childNodes name=lastChild />"
            "<img id=exploitImg src=0 onerror='alert(1)' />"
            "</div></form>",
        "");

    // Walking templates triggers a recursive sanitization call, which shouldn't
    // invalidate the information collected from the previous visit of the later
    // nodes in the walk.
    testHtml(
        'DOM clobbering with recursive sanitize call using templates',
        validator,
        "<form><div>"
          "<input id=childNodes />"
          "<template></template>"
          "<input id=childNodes name=lastChild />"
          "<img id=exploitImg src=0 onerror='alert(1)' />"
          "</div></form>",
        "");

  /// Number of tree modifications this instance has made.
  int numTreeModifications = 0;
    // Walk the tree until no new modifications are added to the tree.
    var previousTreeModifications;
    do {
      previousTreeModifications = numTreeModifications;
    } while (previousTreeModifications != numTreeModifications);
    numTreeModifications++;