Prevent the use methods similar to eval()

Metadata

ID: typescript-best-practices/no-implied-eval

Language: TypeScript

Severity: Warning

Category: Security

Description

JavaScript methods like setTimeout()setInterval(), or execScript() can accept a string of code as their first argument. This code will be executed at runtime, opening a vector for potential attacks.

It is generally considered a bad practice to execute code at runtime. This rule considers these methods as implied evaluations when their parameter is a piece of code.

Non-Compliant Code Examples

setTimeout("x = 1;");
setTimeout("x = 1;", 100);
setInterval("x = 1;");
execScript("x = 1;");
// const s = 'x=1'; setTimeout(s, 100);
setTimeout(String('x=1'), 100);

// member expressions
window.setTimeout('foo');
window.setInterval('foo');
window['setTimeout']('foo');
window['setInterval']('foo');
window[`setInterval`]('foo');
window.window['setInterval']('foo');
global.setTimeout('foo');
global.setInterval('foo');
global['setTimeout']('foo');
global['setInterval']('foo');
global[`setInterval`]('foo');
global.global['setInterval']('foo');
globalThis.setTimeout('foo');
globalThis.setInterval('foo');

// template literals
setTimeout(`foo${bar}`);
window.setTimeout(`foo${bar}`);
window.window.setTimeout(`foo${bar}`);
global.global.setTimeout(`foo${bar}`);

// string concatenation
setTimeout('foo' + bar);
setTimeout(foo + 'bar');
setTimeout(`foo` + bar);
setTimeout(1 + ';' + 1);
window.setTimeout('foo' + bar);
window.setTimeout(foo + 'bar');
window.setTimeout(`foo` + bar);
window.setTimeout(1 + ';' + 1);
window.window.setTimeout(1 + ';' + 1);
global.setTimeout('foo' + bar);
global.setTimeout(foo + 'bar');
global.setTimeout(`foo` + bar);
global.setTimeout(1 + ';' + 1);
global.global.setTimeout(1 + ';' + 1);
globalThis.setTimeout('foo' + bar);

// gives the correct node when dealing with nesting
setTimeout('foo' + (function() {
   setTimeout(helper);
   execScript('str');
   return 'bar';
})());

window.setTimeout('foo' + (function() {
   setTimeout(helper);
   window.execScript('str');
   return 'bar';
})());

global.setTimeout('foo' + (function() {
   setTimeout(helper);
   global.execScript('str');
   return 'bar';
})());

// Optional chaining
window?.setTimeout('code', 0);
(window?.setTimeout)('code', 0);

Compliant Code Examples

setTimeout();

setTimeout;
setTimeout = foo;
window.setTimeout;
window.setTimeout = foo;
window['setTimeout'];
window['setTimeout'] = foo;
global.setTimeout;
global.setTimeout = foo;
global['setTimeout'];
global['setTimeout'] = foo;
globalThis['setTimeout'] = foo;

window[`SetTimeOut`]('foo', 100);
global[`SetTimeOut`]('foo', 100);
global[`setTimeout${foo}`]('foo', 100);
global[`setTimeout${foo}`]('foo', 100);
globalThis[`setTimeout${foo}`]('foo', 100);

// normal usage
setTimeout(function() { x = 1; }, 100);
setInterval(function() { x = 1; }, 100)
execScript(function() { x = 1; }, 100)
window.setTimeout(function() { x = 1; }, 100);
window.setInterval(function() { x = 1; }, 100);
window.execScript(function() { x = 1; }, 100);
window.setTimeout(foo, 100);
window.setInterval(foo, 100);
window.execScript(foo, 100);
global.setTimeout(function() { x = 1; }, 100);
global.setInterval(function() { x = 1; }, 100);
global.execScript(function() { x = 1; }, 100);
global.setTimeout(foo, 100);
global.setInterval(foo, 100);
global.execScript(foo, 100);
globalThis.setTimeout(foo, 100);

// only checks on top-level statements or window.*
foo.setTimeout('hi')

// identifiers are fine
setTimeout(foo, 10)
setInterval(1, 10)
execScript(2)

// as are function expressions
setTimeout(function() {}, 10)

// setInterval
foo.setInterval('hi')
setInterval(foo, 10)
setInterval(function() {}, 10)

// execScript
foo.execScript('hi')
execScript(foo)
execScript(function() {})

// a binary plus on non-strings doesn't guarantee a string
// setTimeout(foo + bar, 10)

// doesn't check anything but the first argument
setTimeout(foobar, 'buzz')
setTimeout(foobar, foo + 'bar')

// only checks immediate subtrees of the argument
setTimeout(function() { return 'foobar'; }, 10)

// https://github.com/eslint/eslint/issues/7821
setTimeoutFooBar('Foo Bar')

foo.window.setTimeout('foo', 100);
foo.global.setTimeout('foo', 100);
// var window; window.setTimeout('foo', 100);
// var global; global.setTimeout('foo', 100);
// function foo(window) { window.setTimeout('foo', 100); }
// function foo(global) { global.setTimeout('foo', 100); }
foo('', window.setTimeout);
foo('', global.setTimeout);
https://static.datadoghq.com/static/images/logos/github_avatar.svg https://static.datadoghq.com/static/images/logos/vscode_avatar.svg jetbrains

Seamless integrations. Try Datadog Code Analysis