UNPKG

@locker/eslint-plugin-unsafe-types

Version:
152 lines (139 loc) 7.56 kB
/** Original file https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-eval.js * @fileoverview Detect usage of unsigned eval calls. * @author Lightning Web Security Team */ 'use strict'; //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/unsafe-eval'); //------------------------------------------------------------------------------ // Tests //------------------------------------------------------------------------------ const env = { browser: true, commonjs: true, es2024: true, jquery: true }; const ruleTester = new RuleTester(); ruleTester.run('unsafe-eval', rule, { valid: [ 'Eval(foo)', "setTimeout('foo')", "setInterval('foo')", "window.setTimeout('foo')", "window.setInterval('foo')", "window.noeval('foo')", "function foo() { var eval = 'foo'; window[eval]('foo') }", "globalThis.noneval('foo')", "function foo() { var eval = 'foo'; globalThis[eval]('foo') }", "this.noeval('foo');", "function foo() { 'use strict'; this.eval('foo'); }", "var obj = {foo: function() { this.eval('foo'); }}", "var obj = {}; obj.foo = function() { this.eval('foo'); }", "function f() { 'use strict'; () => { this.eval('foo') } }", "(function f() { 'use strict'; () => { this.eval('foo') } })", 'class A { foo() { this.eval(); } }', 'class A { static foo() { this.eval(); } }', 'class A { field = this.eval(); }', 'class A { field = () => this.eval(); }', 'class A { static { this.eval(); } }', // User-defined this.eval in callbacks "array.findLast(function (x) { return this.eval.includes(x); }, { eval: ['foo', 'bar'] });", 'callbacks.findLastIndex(function (cb) { return cb(this.eval); }, this);', "['1+1'].flatMap(function (str) { return this.eval(str); }, new Evaluator);", // Signed direct eval "eval($A.lockerService.trusted.createScript('foo'))", "eval($A.$lockerService$.$trusted$.$createScript$('foo'))", "eval($A.lockerService.restricted.createScript('foo'))", "eval($A.$lockerService$.$restricted$.$createScript$('foo'))", 'eval($A.lockerService.trusted.createScript(foo))', "this.eval($A.lockerService.trusted.createScript('foo'));", "'use strict'; this.eval($A.lockerService.trusted.createScript('foo'));", "function foo(eval) { eval($A.lockerService.trusted.createScript('foo')) }", "function foo() { this.eval($A.lockerService.trusted.createScript('foo')); }", "() => { this.eval($A.lockerService.trusted.createScript('foo')) }", 'eval($A.lockerService.trusted.createScript(foo))', "eval($A.lockerService.trusted.createScript('foo'))", "window.eval($A.lockerService.trusted.createScript('foo'))", "global.eval($A.lockerService.trusted.createScript('foo'))", "globalThis.eval($A.lockerService.trusted.createScript('foo'))", // Signed indirect eval "(0, eval)($A.lockerService.trusted.createScript('foo'))", "(0, window.eval)($A.lockerService.trusted.createScript('foo'))", "(0, window['eval'])($A.lockerService.trusted.createScript('foo'))", "() => { this.eval($A.lockerService.trusted.createScript('foo')); }", "() => { 'use strict'; this.eval($A.lockerService.trusted.createScript('foo')); }", "'use strict'; () => { this.eval($A.lockerService.trusted.createScript('foo')); }", "() => { 'use strict'; () => { this.eval($A.lockerService.trusted.createScript('foo')); } }", "window.window.eval($A.lockerService.trusted.createScript('foo'))", "window.window['eval']($A.lockerService.trusted.createScript('foo'))", "global.global.eval($A.lockerService.trusted.createScript('foo'))", "global.global[`eval`]($A.lockerService.trusted.createScript('foo'))", "this.eval($A.lockerService.trusted.createScript('foo'))", "'use strict'; this.eval($A.lockerService.trusted.createScript('foo'))", "function foo() { this.eval($A.lockerService.trusted.createScript('foo')) }", "globalThis.globalThis.eval($A.lockerService.trusted.createScript('foo'))", "globalThis.globalThis['eval']($A.lockerService.trusted.createScript('foo'))", "(0, globalThis.eval)($A.lockerService.trusted.createScript('foo'))", "(0, globalThis['eval'])($A.lockerService.trusted.createScript('foo'))", "var EVAL = eval; EVAL($A.lockerService.trusted.createScript('foo'))", ].map((code) => ({ code, env })), invalid: [ // Direct eval "eval(foo);eval($A.lockerService.trusted.createScript('foo'))", 'eval(foo)', "eval('foo')", "function foo(eval) { eval('foo') }", "function foo() { this.eval('foo'); }", "() => { this.eval('foo') }", 'eval(foo)', "eval('foo')", "function foo(eval) { eval('foo') }", "window.eval('foo')", "global.eval('foo')", // Indirect eval "(0, eval)('foo')", "(0, window.eval)('foo')", "(0, window['eval'])('foo')", "var EVAL = eval; EVAL('foo')", "var EVAL = this.eval; EVAL('foo')", "var EVAL = this.eval; EVAL($A.lockerService.trusted.createScript('foo'))", "'use strict'; var EVAL = this.eval; EVAL('foo')", "'use strict'; var EVAL = this.eval; EVAL($A.lockerService.trusted.createScript('foo'))", "() => { this.eval('foo'); }", "() => { 'use strict'; this.eval('foo'); }", "'use strict'; () => { this.eval('foo'); }", "() => { 'use strict'; () => { this.eval('foo'); } }", "(function(exe){ exe('foo') })(eval);", "(function(exe){ exe($A.lockerService.trusted.createScript('foo')) })(eval);", "window.eval('foo')", "window.window.eval('foo')", "window.window['eval']('foo')", "global.eval('foo')", "global.global.eval('foo')", "global.global[`eval`]('foo')", "this.eval('foo')", "'use strict'; this.eval('foo')", "function foo() { this.eval('foo') }", "var EVAL = globalThis.eval; EVAL('foo')", "globalThis.eval('foo')", "globalThis.globalThis.eval('foo')", "globalThis.globalThis['eval']('foo')", "(0, globalThis.eval)('foo')", "(0, globalThis['eval'])('foo')", // Optional chaining "window?.eval('foo')", "(window?.eval)('foo')", "(window?.window).eval('foo')", // Class fields "class C { [this.eval('foo')] }", "'use strict'; class C { [this.eval('foo')] }", 'class A { static {} [this.eval()]; }', // this.eval in callbacks (not user-defined) "array.findLast(x => this.eval.includes(x), { eval: 'abc' });", 'callbacks.findLastIndex(function (cb) { return cb(eval); }, this);', "['1+1'].flatMap(function (str) { return this.eval(str); });", "['1'].reduce(function (a, b) { return this.eval(a) ? a : b; }, '0');", // Signed using wrong syntax "eval($A.lockerService.trusted['createScript']('foo'))", "eval($A.lockerService.trusted.createScript.call($A.lockerService.trusted, 'foo'))", ].map((code) => ({ code, env, errors: [{ messageId: 'unexpected' }] })), });