/**
* @file Test for no-unsanitized rule
* @author Frederik Braun et al.
* @copyright 2015-2017 Mozilla Corporation. All rights reserved
*/
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const rule = require("../../lib/rules/method");
const RuleTester = require("eslint").RuleTester;
const { ESLint } = require("eslint");
const preESLintv9 = ESLint.version.split(".")[0] < 9;
const PATH_TO_BABEL_ESLINT = `${process.cwd()}/node_modules/@babel/eslint-parser/`;
const PATH_TO_TYPESCRIPT_ESLINT = preESLintv9
? `${process.cwd()}/node_modules/@typescript-eslint/parser/dist`
: `@typescript-eslint/parser`;
const babelParser = require(PATH_TO_BABEL_ESLINT);
const typescriptParser = require(PATH_TO_TYPESCRIPT_ESLINT);
const ECMA_VERSION_6_ONLY_OPTIONS = preESLintv9
? {
parserOptions: { ecmaVersion: 6 },
}
: {
languageOptions: { parserOptions: { ecmaVersion: 6 } },
};
const ECMA_VERSION_8_ONLY_OPTIONS = preESLintv9
? {
parserOptions: { ecmaVersion: 8 },
}
: {
languageOptions: { parserOptions: { ecmaVersion: 8 } },
};
const ECMA_VERSION_2020_ONLY_OPTIONS = preESLintv9
? {
parserOptions: { ecmaVersion: 2020 },
}
: {
languageOptions: { parserOptions: { ecmaVersion: 2020 } },
};
const BABEL_ONLY_OPTIONS = preESLintv9
? {
parser: PATH_TO_BABEL_ESLINT,
}
: {
languageOptions: {
parser: babelParser,
},
};
const BABEL_OPTIONS_FOR_FLOW = preESLintv9
? {
parser: PATH_TO_BABEL_ESLINT,
parserOptions: {
requireConfigFile: false,
babelOptions: {
plugins: ["@babel/plugin-syntax-flow"],
},
},
}
: {
languageOptions: {
parser: babelParser,
parserOptions: {
requireConfigFile: false,
babelOptions: {
plugins: ["@babel/plugin-syntax-flow"],
},
},
},
};
const TYPESCRIPT_OPTIONS = preESLintv9
? {
parser: PATH_TO_TYPESCRIPT_ESLINT,
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
},
}
: {
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
},
},
};
const FANTASY_CALLEE_OPTIONS = preESLintv9
? {
parser: require.resolve("../parsers/fantasy-callee"),
}
: {
languageOptions: {
parser: require("../parsers/fantasy-callee"),
},
};
//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------
const eslintTester = new RuleTester();
eslintTester.run("method", rule, {
// Examples of code that should not trigger the rule
// XXX this does not find z['innerHTML'] and the like.
valid: [
// tests for insertAdjacentHTML calls
{
code: "n.insertAdjacentHTML('afterend', 'meh');",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "n.insertAdjacentHTML('afterend', `
`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "n.insertAdjacentHTML('afterend', Sanitizer.escapeHTML`${title}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// document.write/writeln
{
code: "document.write('lulz');",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "document.write();",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "document.writeln(Sanitizer.escapeHTML`${evil}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "otherNodeWeDontCheckFor.writeln(evil);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Native method (Check customize code doesn't include these)
{
code: "document.toString(evil);",
},
{
code: "document.write(escaper(x))",
options: [
{
escape: {
methods: ["escaper"],
},
},
],
},
// Checking write can be overriden
{
code: "document.write(evilest)",
options: [
{
objectMatches: ["document", "documentFun"],
},
{
write: {
objectMatches: ["thing"],
},
},
],
},
// Checking disableDefault can remove the default rules
{
code: "document.write(evil)",
options: [
{
defaultDisable: true,
},
],
},
// rule should not barf on a CallExpression result being called again
{
code: " _tests.shift()();",
},
{
code: "(Async.checkAppReady = function() { return true; })();",
},
{
code: "let endTime = (mapEnd || (e => e.delta))(this._data[this._data.length - 1]);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "(text.endsWith('\\n') ? document.write : document.writeln)(text)",
},
// issue 71 https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/71
{
code: "function foo() { return this().bar(); };",
},
// issue 73 https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/73
{
code: "new Function()();",
},
{
// issue 79
code: "range.createContextualFragment('
Hello!
');",
},
{
// issue 79
code: "range.createContextualFragment(Sanitizer.escapeHTML`${evil}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
methods: ["escaper"],
},
},
],
},
{
// issue 79
code: "range.createContextualFragment(escaper(''+evil+''));",
options: [
{
escape: {
methods: ["escaper"],
},
},
],
},
// Issue 135: Check literal imports in all parsers:
{
code: "import('lodash')",
...ECMA_VERSION_2020_ONLY_OPTIONS,
},
// Issue 83: Support import() expressions as parsed by @babel/eslint-parser
{
code: "import('lodash')",
...BABEL_ONLY_OPTIONS,
},
// Issue 135: Check literal imports in all parsers:
{
code: "import('lodash')",
...TYPESCRIPT_OPTIONS,
},
{
// issue 108: adding tests for custom escaper
code: "range.createContextualFragment(templateEscaper`${evil}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
taggedTemplates: ["templateEscaper"],
},
},
],
},
{
// issue 108: adding tests for custom escaper
code: "n.insertAdjacentHTML('afterend', DOMPurify.sanitize(evil));",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
methods: ["DOMPurify.sanitize"],
},
},
],
},
{
// issue 108: adding tests for custom escaper
code: "n.insertAdjacentHTML('afterend', DOMPurify.sanitize(evil, options));",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
methods: ["DOMPurify.sanitize"],
},
},
],
},
{
// issue 108: adding tests for custom escaper
code: "n.insertAdjacentHTML('afterend', DOMPurify.sanitize(evil, {ALLOWED_TAGS: ['b']}));",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
methods: ["DOMPurify.sanitize"],
},
},
],
},
{
// issue 154: Adding tests for TaggedTemplateExpression callee https://jestjs.io/docs/api#2-describeeachtablename-fn-timeout
code: "describe.each`table`(name, fn, timeout)",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "document.write`text`",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "document.write`text ${'static string'}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "custom`text ${variable}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{},
{
custom: {
properties: [0],
},
},
],
},
{
code: "custom`text ${'string'}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{},
{
custom: {
properties: [1],
},
},
],
},
{
// This is allowed because of how tagged templates pass function parameters
code: "document.write`text ${variable}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
// basic support for SequenceExpressions, which always return the last item - fixes #113
code: "let a = (0,1,2,34);",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
// issue #122 calling an await expression
code: "(async function() { (await somePromise)(); })",
...ECMA_VERSION_8_ONLY_OPTIONS,
},
{
// issue #122 calling an await expression
// note how we won't be able to tell if the promise resolves to foo.insertAdjacentHTML
code: "async () => (await TheRuleDoesntKnowWhatIsBeingReturnedHere())('afterend', blah);",
...ECMA_VERSION_2020_ONLY_OPTIONS,
},
{
// Regression test for #124, make sure we don't raise an "Unexpected Callee" error.
code: "(e = this.n[n.i])(i, r)",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
// Regression test for #124, make sure we go deeper into validating the AssignmentExpression.
code: "(e = node.insertAdjacentHTML('beforebegin', 'safe'))()",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Typescript support tests
{
code: "node.insertAdjacentHTML('beforebegin', (5 as string));",
...TYPESCRIPT_OPTIONS,
},
{
code: "node!.insertAdjacentHTML('beforebegin', 'raw string');",
...TYPESCRIPT_OPTIONS,
},
{
code: "node!().insertAdjacentHTML('beforebegin', 'raw string');",
...TYPESCRIPT_OPTIONS,
},
// Flow support tests
{
code: "(node: HTMLElement).insertAdjacentHTML('beforebegin', 'raw string');",
...BABEL_OPTIONS_FOR_FLOW,
},
{
code: "node.insertAdjacentHTML('beforebegin', (5: string));",
...BABEL_OPTIONS_FOR_FLOW,
},
{
code: "(insertAdjacentHTML: function)('afterend', 'static string');",
...BABEL_OPTIONS_FOR_FLOW,
},
// Issue 135: method calls to import should not warn.
{
code: "foo.import(bar)",
...ECMA_VERSION_2020_ONLY_OPTIONS,
},
{
code: "foo.import(bar)",
...BABEL_ONLY_OPTIONS,
},
{
code: "foo.import(bar)",
...TYPESCRIPT_OPTIONS,
},
// let without initialization.
{
code: "let c; n.insertAdjacentHTML('beforebegin', c)",
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "x.setHTML(evil)",
},
{
code: "x.setHTML(evil, { sanitizer: s })",
},
{
code: "x.setHTML(evil, { sanitizer: new Sanitizer()})",
},
{
code: "(info.current = type)(child_ctx)",
},
{
code: "(info.current = n.insertAdjacentHTML)('beforebegin', 'innocent')",
},
{
// #214: We also allow *harmful* parameters.
code: "let l = ['afterend', 'harmless']; foo.insertAdjacentHTML(...l);",
...ECMA_VERSION_2020_ONLY_OPTIONS,
},
{
// #214: We also allow *harmful* parameters.
code: "foo.insertAdjacentHTML(wrongParamCount);",
...ECMA_VERSION_2020_ONLY_OPTIONS,
},
{
// # 232: disallow setHTMLUnsafe, but OK with static string.
code: "foo.setHTMLUnsafe('static string')",
},
],
// Examples of code that should trigger the rule
invalid: [
/* XXX Do NOT change the error strings below without review from freddy:
* The strings are optimized for SEO and understandability.
* The developer can search for them and will find this MDN article:
* https://developer.mozilla.org/en-US/Firefox_OS/Security/Security_Automation
*/
// insertAdjacentHTML examples
{
code: "node.insertAdjacentHTML('beforebegin', htmlString);",
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "node.insertAdjacentHTML('beforebegin', template.getHTML());",
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
// document.write / writeln
{
code: "document.write(''+ htmlInput + '');",
errors: [
{
message: "Unsafe call to document.write for argument 0",
type: "CallExpression",
},
],
},
{
code: "documentish.write(''+ htmlInput + '');",
errors: [
{
message: "Unsafe call to documentish.write for argument 0",
type: "CallExpression",
},
],
},
{
code: "documentIframe.write(''+ htmlInput + '');",
errors: [
{
message:
"Unsafe call to documentIframe.write for argument 0",
type: "CallExpression",
},
],
},
{
code: "document.writeln(evil);",
errors: [
{
message: "Unsafe call to document.writeln for argument 0",
type: "CallExpression",
},
],
},
{
code: "window.document.writeln(bad);",
errors: [
{
message:
"Unsafe call to window.document.writeln for argument 0",
type: "CallExpression",
},
],
},
// issue 71 https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/71
{
code: "function foo() { return this().insertAdjacentHTML(foo, bar); };",
errors: [
{
message:
"Unsafe call to this().insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Broken config
{
code: "b.boop(pie)",
options: [
{},
{
boop: {},
},
],
errors: [
{
message:
"Method check requires properties array in eslint rule boop",
type: "CallExpression",
},
],
},
// Checking disableDefault can remove the default rules but also add more
{
code: "document.write(evil); b.thing(x); b.other(me);",
options: [
{
defaultDisable: true,
},
{
thing: {},
other: {
properties: [0],
},
},
],
errors: [
{
message:
"Method check requires properties array in eslint rule thing",
type: "CallExpression",
},
{
message: "Unsafe call to b.other for argument 0",
type: "CallExpression",
},
],
},
// Test that stem from former parser errors and breakage
{
code: "getDocument(myID).write(evil)",
errors: [
{
message:
"Unsafe call to getDocument(myID).write for argument 0",
type: "CallExpression",
},
],
},
// Issue 79: Warn for use of createContextualFragment
{
code: "range.createContextualFragment(badness)",
errors: [
{
message:
"Unsafe call to range.createContextualFragment for argument 0",
type: "CallExpression",
},
],
},
// Issue 135: Disallow import() with non-literal params
{
code: "import(foo)",
...ECMA_VERSION_2020_ONLY_OPTIONS,
errors: [
{
message: "Unsafe call to import for argument 0",
type: "ImportExpression",
},
],
},
{
code: "import(foo)",
...BABEL_ONLY_OPTIONS,
errors: [
{
message: "Unsafe call to import for argument 0",
type: "ImportExpression",
},
],
},
{
code: "import(foo)",
...TYPESCRIPT_OPTIONS,
errors: [
{
message: "Unsafe call to import for argument 0",
type: "ImportExpression",
},
],
},
{
// basic support for SequenceExpressions, which always return the last item - fixes #113
code: "(0, node.insertAdjacentHTML)('beforebegin', evil);",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// issue 108: adding tests for custom escaper
// in this case we allow a function for templates, but it's used as a method
code: "n.insertAdjacentHTML('afterend', templateEscaper(evil, options));",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
taggedTemplates: ["templateEscaper"],
},
},
],
errors: [
{
message:
"Unsafe call to n.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// issue 108: adding tests for custom escaper
// in this case we allow a function for methods, but it's used fo template strings
code: "n.insertAdjacentHTML('afterend', sanitize`${evil}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
escape: {
methods: ["sanitize"],
},
},
],
errors: [
{
message:
"Unsafe call to n.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "document.writeln(Sanitizer.escapeHTML`${evil}`);",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{
defaultDisable: true,
},
{
// check first parameter to .writeLn(), as long as the preceeding object matches the regex "document"
writeln: {
objectMatches: ["document"],
properties: [0],
escape: {
methods: [],
taggedTemplates: [],
},
},
},
],
errors: [
{
message: "Unsafe call to document.writeln for argument 0",
type: "CallExpression",
},
],
},
// issue 154: Adding tests for TaggedTemplateExpression callee https://jestjs.io/docs/api#2-describeeachtablename-fn-timeout
{
code: "describe.each`table${node.insertAdjacentHTML('beforebegin', htmlString)}`(name, fn, timeout)",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "describe.each`table${document.writeln(evil)}`(name, fn, timeout)",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message: "Unsafe call to document.writeln for argument 0",
type: "CallExpression",
},
],
},
{
code: "node.insertAdjacentHTML`text ${variable}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "TaggedTemplateExpression",
},
],
},
{
code: "custom`text ${variable}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{},
{
custom: {
properties: [1],
},
},
],
errors: [
{
message: "Unsafe call to custom for argument 1",
type: "TaggedTemplateExpression",
},
],
},
{
code: "custom`text ${variable} ${variable2}`",
...ECMA_VERSION_6_ONLY_OPTIONS,
options: [
{},
{
custom: {
properties: [2],
},
},
],
errors: [
{
message: "Unsafe call to custom for argument 2",
type: "TaggedTemplateExpression",
},
],
},
{
// admittedly, this doesnt make a lot of sense, since the func doesnt return a promise
code: "async () => await foo.insertAdjacentHTML('afterend', blah);",
...ECMA_VERSION_2020_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to foo.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// admittedly, this doesnt make a lot of sense, since the func doesnt return a promise
code: "async () => (await foo.insertAdjacentHTML('afterend', blah))();",
...ECMA_VERSION_2020_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to foo.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "async () => (await foo)().insertAdjacentHTML('afterend', blah);",
...ECMA_VERSION_2020_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to (await foo)().insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// AssignmentExpression, ensure we are detecting the pattern from the right part - Regression test for #124
code: "(e = node.insertAdjacentHTML)('beforebegin', evil)",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// Regression test for #124, make sure we go deeper and detect the unsafe pattern
code: "(e = node.insertAdjacentHTML('beforebegin', evil))()",
...ECMA_VERSION_6_ONLY_OPTIONS,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "(9)()",
errors: [
{
message:
"Error in no-unsanitized: Unexpected Callee. Please report a minimal code snippet to the developers at https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/new?title=Unsupported%20Callee%20of%20type%20Literal%20for%20CallExpression",
type: "Literal",
},
],
},
// Typescript test cases
//
// Null coalescing operator
{
code: "node!().insertAdjacentHTML('beforebegin', htmlString);",
...TYPESCRIPT_OPTIONS,
errors: [
{
message:
"Unsafe call to node!().insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "node!.insertAdjacentHTML('beforebegin', htmlString);",
...TYPESCRIPT_OPTIONS,
errors: [
{
message:
"Unsafe call to node!.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "(x as HTMLElement).insertAdjacentHTML('beforebegin', htmlString)",
...TYPESCRIPT_OPTIONS,
errors: [
{
message:
"Unsafe call to x as HTMLElement.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
// Flow test cases
{
code: "(node: HTMLElement).insertAdjacentHTML('beforebegin', unsafe);",
...BABEL_OPTIONS_FOR_FLOW,
errors: [
{
message:
"Unsafe call to node: HTMLElement.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "node.insertAdjacentHTML('beforebegin', (unsafe: string));",
...BABEL_OPTIONS_FOR_FLOW,
errors: [
{
message:
"Unsafe call to node.insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
code: "(insertAdjacentHTML: function)('beforebegin', unsafe);",
...BABEL_OPTIONS_FOR_FLOW,
errors: [
{
message: "Unsafe call to insertAdjacentHTML for argument 1",
type: "CallExpression",
},
],
},
{
// This test ensures we do not allow _var_ declarations traced back as "safe"
// because it could be modified through dynamical global scope operations,
// e.g., globalThis['copies'] and we don't want to trace through those.
code: "var copies = 'safe'; /* some modifications with globalThis['copies'] */; n.insertAdjacentHTML('beforebegin', copies);",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1/,
type: "CallExpression",
},
],
},
{
code: "let copies = evil; n.insertAdjacentHTML('beforebegin', copies);",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1 \(Variable 'copies' initialized with unsafe value at \d+:\d+\)/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "let copies = 'safe'; copies = suddenlyUnsafe; n.insertAdjacentHTML('beforebegin', copies);",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1 \(Variable 'copies' reassigned with unsafe value at \d+:\d+\)/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Variable tracked back to a parameter part of a FunctionDeclaration.
{
code: "function test(evil) { let copies = 'safe'; copies = evil; n.insertAdjacentHTML('beforebegin', copies); }",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1 \(Variable 'evil' declared as function parameter, which is considered unsafe. 'FunctionDeclaration' at \d+:\d+\)/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Variable tracked back to a parameter part of a FunctionExpression.
{
code: "const fn = function (evil) { let copies = 'safe'; copies = evil; n.insertAdjacentHTML('beforebegin', copies); }",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1 \(Variable 'evil' declared as function parameter, which is considered unsafe. 'FunctionExpression' at \d+:\d+\)/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
// Variable tracked back to a parameter part of a ArrowFunctionExpression.
{
code: "const fn = (evil) => { let copies = 'safe'; copies = evil; n.insertAdjacentHTML('beforebegin', copies); }",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1 \(Variable 'evil' declared as function parameter, which is considered unsafe. 'ArrowFunctionExpression' at \d+:\d+\)/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "§fantasyCallee§()",
...FANTASY_CALLEE_OPTIONS,
errors: [
{
message:
"Error in no-unsanitized: Unexpected Callee. Please report a minimal code snippet to the developers at https://github.com/mozilla/eslint-plugin-no-unsanitized/issues/new?title=Unsupported%20Callee%20of%20type%20FantasyCallee%20for%20CallExpression",
type: "FantasyCallee",
},
],
},
{
code: `
let c;
if (cond) {
c = 'safe';
} else {
c = evil;
}
n.insertAdjacentHTML('beforebegin', \`\${c}\`);
`,
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1/,
type: "CallExpression",
},
],
...ECMA_VERSION_6_ONLY_OPTIONS,
},
{
code: "(info.current = n.insertAdjacentHTML)('beforebegin', c)",
errors: [
{
message:
/Unsafe call to n.insertAdjacentHTML for argument 1/,
type: "CallExpression",
},
],
},
{
code: "foo.setHTMLUnsafe(badness)",
errors: [
{
message: /Unsafe call to foo.setHTMLUnsafe for argument 0/,
type: "CallExpression",
},
],
},
],
});