tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 24853c3c9f7b03d4c7f479ae0175a59702bfade6
parent 7af27067438e287edde460a32cc5f234c15b261f
Author: Tom Schuster <tschuster@mozilla.com>
Date:   Tue, 21 Oct 2025 12:02:59 +0000

Bug 1995299 - More tests for the Sanitizer constructor. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D269375

Diffstat:
Mtesting/web-platform/tests/sanitizer-api/sanitizer-config.tentative.html | 226++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 155 insertions(+), 71 deletions(-)

diff --git a/testing/web-platform/tests/sanitizer-api/sanitizer-config.tentative.html b/testing/web-platform/tests/sanitizer-api/sanitizer-config.tentative.html @@ -231,89 +231,129 @@ test(() => { // This is tested in the sanitizer-config test file. // 4. None of config[elements], config[removeElements], config[replaceWithChildrenElements], config[attributes], or config[removeAttributes], if they exist, has duplicates. +const DUPLICATE_NAMES = [ + ["", ""], + ["abc", "abc"], + ["data-xyz", "data-xyz"], + ["abc", {name: "abc"}], + [{name: "abc", namespace: "xyz"}, {name: "abc", namespace: "xyz"}], + [{name: "abc", namespace: ""}, {name: "abc", namespace: null}] +]; + +// NOTE: Elements and attributes have different default namespaces. +const DUPLICATE_ELEMENT_NAMES = DUPLICATE_NAMES.concat([ + ["abc", {name: "abc", namespace: "http://www.w3.org/1999/xhtml"}], + [{name: "abc"}, {name: "abc", namespace: "http://www.w3.org/1999/xhtml"}] +]); + +const DUPLICATE_ATTRIBUTE_NAMES = DUPLICATE_NAMES.concat([ + ["abc", {name: "abc", namespace: null}], + [{name: "abc"}, {name: "abc", namespace: null}] +]); + test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ elements: ["div", { name: "div" }] }); - }); + for (let names of DUPLICATE_ELEMENT_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ elements: names }); + }); + } }, "config[elements] should not allow duplicates"); test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ removeElements: ["div", { name: "div" }] }); - }); + for (let names of DUPLICATE_ELEMENT_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ removeElements: names }); + }); + } }, "config[removeElements] should not allow duplicates"); test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ replaceWithChildrenElements: ["div", { name: "div" }] }); - }); + for (let names of DUPLICATE_ELEMENT_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ replaceWithChildrenElements: names }); + }); + } }, "config[replaceWithChildrenElements] should not allow duplicates"); test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ attributes: ["title", { name: "title" }] }); - }); + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ attributes: names }); + }); + } }, "config[attributes] should not allow duplicates"); test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ removeAttributes: ["title", { name: "title" }] }); - }); + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ removeAttributes: names }); + }); + } }, "config[removeAttributes] should not allow duplicates"); // 5. If both config[elements] and config[replaceWithChildrenElements] exist, then the intersection of config[elements] and config[replaceWithChildrenElements] is empty. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - elements: ["div"], - replaceWithChildrenElements: ["div"], + for (let [a, b] of DUPLICATE_ELEMENT_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + elements: [a], + replaceWithChildrenElements: [b], + }); }); - }); + } }, "config[elements] and config[replaceWithChildrenElements] should not intersect"); // 6. If both config[removeElements] and config[replaceWithChildrenElements] exist, then the intersection of config[removeElements] and config[replaceWithChildrenElements] is empty. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - removeElements: ["div"], - replaceWithChildrenElements: ["div"], + for (let [a, b] of DUPLICATE_ELEMENT_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + removeElements: [a], + replaceWithChildrenElements: [b], + }); }); - }); + } }, "config[removeElements] and config[replaceWithChildrenElements] should not intersect"); -// If config[attributes] exists: -// Neither element[attributes] nor element[removeAttributes], if they exist, has duplicates. +// 7. If config[attributes] exists: +// 7.1. If config[elements] exists: +// 7.1.1. For each element of config[elements]: +// 7.1.1.1. Neither element[attributes] nor element[removeAttributes], if they exist, has duplicates. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - attributes: [], - elements: [{ name: "div", attributes: ["title", { name: "title" }] }], + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + attributes: [], + elements: [{ name: "div", attributes: names }], + }); }); - }); -}, "Duplicates in element[attributes] should not be allowed."); + } +}, "Duplicates in element[attributes] with config[attributes] should not be allowed."); test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - removeAttributes: [], - elements: [ - { name: "div", removeAttributes: ["title", { name: "title" }] }, - ], + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + attributes: [], + elements: [{ name: "div", removeAttributes: names }], + }); }); - }); -}, "Duplicates in element[removeAttributes] should not be allowed."); + } +}, "Duplicates in element[removeAttributes] with config[attributes] should not be allowed."); -// The intersection of config[attributes] and element[attributes] with default « » is empty. +// 7.1.1.2. The intersection of config[attributes] and element[attributes] with default « » is empty. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - attributes: ["title"], - elements: [{ name: "div", attributes: ["title"] }], + for (let [a, b] of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + attributes: [a], + elements: [{ name: "div", attributes: [b] }], + }); }); - }); + } }, "config[attributes] and element[attributes] should not intersect."); -// element[removeAttributes] with default « » is a subset of config[attributes]. +// 7.1.1.3. element[removeAttributes] with default « » is a subset of config[attributes]. test(() => { assert_throws_js(TypeError, () => { new Sanitizer({ @@ -323,8 +363,8 @@ test(() => { }); }, "element[removeAttributes] should be a subset of config[attributes]"); -// If dataAttributes exists and dataAttributes is true: -// element[attributes] does not contain a custom data attribute. +// 7.1.1.4. If dataAttributes exists and dataAttributes is true: +// 7.1.1.4.1. element[attributes] does not contain a custom data attribute. test(() => { assert_throws_js(TypeError, () => { new Sanitizer({ @@ -333,23 +373,37 @@ test(() => { elements: [{ name: "div", attributes: ["data-foo"] }], }); }); -}, "Per-element allow list with a data attribute must not co-exist with config[dataAttributes] set to true."); -// If dataAttributes is true: -// config[attributes] does not contain a custom data attribute. -test(() => { assert_throws_js(TypeError, () => { new Sanitizer({ attributes: [], dataAttributes: true, + elements: [{ name: "div", attributes: [{ name: "data-bar", namespace: null }] }], + }); + }); +}, "element[attributes] with a data attribute must not co-exist with config[dataAttributes] set to true."); + +// 7.2. If dataAttributes is true: +// 7.2.1. config[attributes] does not contain a custom data attribute. +test(() => { + assert_throws_js(TypeError, () => { + new Sanitizer({ attributes: ["data-bar"], + dataAttributes: true, }); }); -}, "Global attribute allow-list with a data attribute must not co-exist with config[dataAttributes] set to true."); -// If config[removeAttributes] exists: + assert_throws_js(TypeError, () => { + new Sanitizer({ + attributes: [{ name: "data-foo", namespace: null }], + dataAttributes: true, + }); + }); +}, "config[attributes] with a data attribute must not co-exist with config[dataAttributes] set to true."); -// Not both element[attributes] and element[removeAttributes] exist. +// 8. If config[removeAttributes] exists: +// 8.1. If config[elements] exists, then for each element of config[elements]: +// 8.1.1. Not both element[attributes] and element[removeAttributes] exist. test(() => { assert_throws_js(TypeError, () => { new Sanitizer({ @@ -359,33 +413,63 @@ test(() => { }); }, "element[attributes] and element[removeAttributes] should not both exist with config[removeAttributes]."); -// The intersection of config[removeAttributes] and element[attributes] with default « » is empty. +// 8.1.2. Neither element[attributes] nor element[removeAttributes], if they exist, has duplicates. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - removeAttributes: ["class"], - elements: [{ name: "div", attributes: ["class"] }], + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + removeAttributes: [], + elements: [{ name: "div", attributes: names }], + }); }); - }); + } +}, "Duplicates in element[attributes] with config[removeAttributes] should not be allowed."); + +test(() => { + for (let names of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + removeAttributes: [], + elements: [{ name: "div", removeAttributes: names }], + }); + }); + } +}, "Duplicates in element[removeAttributes] with config[removeAttributes] should not be allowed."); + +// 8.1.3. The intersection of config[removeAttributes] and element[attributes] with default « » is empty. +test(() => { + for (let [a, b] of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + removeAttributes: [a], + elements: [{ name: "div", attributes: [b] }], + }); + }); + } }, "config[removeAttributes] and element[attributes] should not intersect."); -// The intersection of config[removeAttributes] and element[removeAttributes] with default « » is empty. +// 8.1.4. The intersection of config[removeAttributes] and element[removeAttributes] with default « » is empty. test(() => { - assert_throws_js(TypeError, () => { - new Sanitizer({ - removeAttributes: ["class"], - elements: [{ name: "div", removeAttributes: ["class"] }], + for (let [a, b] of DUPLICATE_ATTRIBUTE_NAMES) { + assert_throws_js(TypeError, () => { + new Sanitizer({ + removeAttributes: [a], + elements: [{ name: "div", removeAttributes: [b] }], + }); }); - }); + } }, "config[removeAttributes] and element[removeAttributes] should not intersect."); -// config[dataAttributes] is an extension of the config[attributes] allow-list. It isn't compatible work with a block-list approach. +// 8.2. config[dataAttributes] does not exist. test(() => { assert_throws_js(TypeError, () => { new Sanitizer({ removeAttributes: [], dataAttributes: true }); }); -}, "Can not use config[dataAttributes] and config[attributes] together."); + assert_throws_js(TypeError, () => { + new Sanitizer({ removeAttributes: [], dataAttributes: false }); + }); +}, "Can not use config[dataAttributes] and config[removeAttributes] together."); </script> </body> </html>