You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: files/en-us/web/javascript/reference/global_objects/eval/index.md
+97-6Lines changed: 97 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,12 @@ sidebar: jssidebar
7
7
---
8
8
9
9
> [!WARNING]
10
-
> Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use `eval()`. See [Never use direct eval()!](#never_use_direct_eval!), below.
10
+
> The argument passed to this method is dynamically evaluated and executed as JavaScript.
11
+
> APIs like this are known as [injection sinks](/en-US/docs/Web/API/Trusted_Types_API#concepts_and_usage), and are potentially a vector for [cross-site-scripting (XSS)](/en-US/docs/Web/Security/Attacks/XSS) attacks.
12
+
>
13
+
> You can mitigate this risk by always passing {{domxref("TrustedScript")}} objects instead of strings and [enforcing trusted types](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types).
14
+
>
15
+
> See [Security considerations](#security_considerations) for more information.
11
16
12
17
The **`eval()`** function evaluates JavaScript code represented as a string and returns its completion value. The source is parsed as a script.
13
18
@@ -36,15 +41,22 @@ eval(script)
36
41
### Parameters
37
42
38
43
-`script`
39
-
- : A string representing a JavaScript expression, statement, or sequence of statements. The expression can include variables and properties of existing objects. It will be parsed as a script, so [`import`](/en-US/docs/Web/JavaScript/Reference/Statements/import) declarations (which can only exist in modules) are not allowed.
44
+
- : A {{domxref("TrustedScript")}} instance or string representing a JavaScript expression, statement, or sequence of statements.
45
+
The expression can include variables and properties of existing objects. It will be parsed as a script, so [`import`](/en-US/docs/Web/JavaScript/Reference/Statements/import) declarations (which can only exist in modules) are not allowed.
40
46
41
47
### Return value
42
48
43
-
The completion value of evaluating the given code. If the completion value is empty, {{jsxref("undefined")}} is returned. If `script` is not a string primitive, `eval()` returns the argument unchanged.
49
+
The completion value of evaluating the given code. If the completion value is empty, {{jsxref("undefined")}} is returned.
50
+
If `script` is not a {{domxref("TrustedScript")}} or string primitive, `eval()` returns the argument unchanged.
44
51
45
52
### Exceptions
46
53
47
-
Throws any exception that occurs during evaluation of the code, including {{jsxref("SyntaxError")}} if `script` fails to be parsed as a script.
54
+
- {{jsxref("SyntaxError")}}
55
+
- : The `script` parameter cannot be parsed as a script.
56
+
- {{jsxref("TypeError")}}
57
+
- : `script` is a string when [Trusted Types](/en-US/docs/Web/API/Trusted_Types_API) are [enforced by a CSP](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) and no default policy is defined.
58
+
59
+
The method also throws any exception that occurs during evaluation of the code.
48
60
49
61
## Description
50
62
@@ -60,7 +72,8 @@ In strict mode, declaring a variable named `eval` or re-assigning `eval` is a {{
60
72
const eval = 1; // SyntaxError: Unexpected eval or arguments in strict mode
61
73
```
62
74
63
-
If the argument of `eval()` is not a string, `eval()` returns the argument unchanged. In the following example, passing a `String` object instead of a primitive causes `eval()` to return the `String` object rather than evaluating the string.
75
+
If the argument of `eval()` is not a {{domxref("TrustedScript")}} or string, `eval()` returns the argument unchanged.
76
+
In the following example, passing a `String` object instead of a primitive causes `eval()` to return the `String` object rather than evaluating the string.
@@ -190,7 +203,10 @@ Indirect eval can be seen as if the code is evaluated within a separate `<script
190
203
191
204
Using direct `eval()` suffers from multiple problems:
192
205
193
-
- `eval()` executes the code it's passed with the privileges of the caller. If you run `eval()` with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, allowing third-party code to access the scope in which `eval()` was invoked (if it's a direct eval) can lead to possible attacks that reads or changes local variables.
206
+
- `eval()` executes the code it's passed with the privileges of the caller.
207
+
If you run `eval()` with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension.
208
+
More importantly, allowing third-party code to access the scope in which `eval()` was invoked (if it's a direct eval) can lead to possible attacks that reads or changes local variables.
209
+
See [Security considerations](#security_considerations) for approaches that mitigate these risks.
194
210
- `eval()` is slower than the alternatives, since it has to invoke the JavaScript interpreter, while many other constructs are optimized by modern JS engines.
195
211
- Modern JavaScript interpreters convert JavaScript to machine code. This means that any concept of variable naming gets obliterated. Thus, any use of `eval()` will force the browser to do long expensive variable name lookups to figure out where the variable exists in the machine code and set its value. Additionally, new things can be introduced to that variable through `eval()`, such as changing the type of that variable, forcing the browser to re-evaluate all of the generated machine code to compensate.
196
212
- Minifiers give up on any minification if the scope is transitively depended on by `eval()`, because otherwise `eval()` cannot read the correct variable at runtime.
@@ -345,8 +361,83 @@ Note that since JSON syntax is limited compared to JavaScript syntax, many valid
345
361
346
362
Passing carefully constrained data instead of arbitrary code is a good idea in general. For example, an extension designed to scrape contents of web-pages could have the scraping rules defined in [XPath](/en-US/docs/Web/XML/XPath) instead of JavaScript code.
347
363
364
+
### Security considerations
365
+
366
+
The method can be used to execute arbitrary input with the privileges of the caller.
367
+
If the input is a potentially unsafe string provided by a user, this is a possible vector for [Cross-site-scripting (XSS)](/en-US/docs/Web/Security/Attacks/XSS) attacks.
368
+
369
+
For example, the following code shows how `eval()` might execute `untrustedCode` provided by a user:
Websites with a [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP) that specifies [`script-src`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src) or [`default-src`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/default-src) will prevent such code running by default.
377
+
If you must allow the scripts to run via `eval()` you can mitigate the risks by always assigning a {{domxref("TrustedScript")}} instance instead of a string, and [enforcing trusted types](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) using the [`require-trusted-types-for`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/require-trusted-types-for) CSP directive.
378
+
This ensures that the input is passed through a transformation function.
379
+
380
+
To allow `eval()` to run, you will additionally need to specify the [`trusted-types-eval` keyword](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#trusted-types-eval) in your CSP `script-src` directive.
381
+
382
+
The [`unsafe-eval`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#unsafe-eval) keyword also allows `eval()`, but is much less safe then `trusted-types-eval` because it would allow execution even on browsers that do not support trusted types.
383
+
384
+
For example, the required CSP for your site might look like this:
The behavior of the transformation function implemented in your trusted types policy will depend on the specific use case that requires a user provided script.
391
+
If possible you should lock the allowed scripts to exactly the code that you trust to run.
392
+
If that is not possible, you might allow or block the use of certain functions within the provided input.
393
+
348
394
## Examples
349
395
396
+
Note that the first example shows how to use the method with trusted types.
397
+
The other examples omit this step for brevity.
398
+
399
+
### Using TrustedScript
400
+
401
+
To mitigate the risk of XSS, we should always assign `TrustedScript` instances to the `script` parameter.
402
+
We also need to do this if we're enforcing trusted types for other reasons and we want to allow some script sources that have been permitted (by `CSP: script-src`).
403
+
404
+
Trusted types are not yet supported on all browsers, so first we define the [trusted types tinyfill](/en-US/docs/Web/API/Trusted_Types_API#trusted_types_tinyfill).
405
+
This acts as a transparent replacement for the Trusted Types JavaScript API:
Next we create a {{domxref("TrustedTypePolicy")}} that defines a {{domxref("TrustedTypePolicy/createScript", "createScript()")}} method for transforming input strings into {{domxref("TrustedScript")}} instances.
413
+
414
+
For the purpose of this example we'll assume that we have a function `transformedScript()` that defines our tranformation/filtering logic.
The **`Function()`** constructor creates {{jsxref("Function")}} objects. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues as {{jsxref("Global_Objects/eval", "eval()")}}. However, unlike `eval` (which may have access to the local scope), the `Function` constructor creates functions which execute in the global scope only.
10
+
> [!WARNING]
11
+
> The arguments passed this method are dynamically evaluated and executed as JavaScript.
12
+
> APIs like this are known as [injection sinks](/en-US/docs/Web/API/Trusted_Types_API#concepts_and_usage), and are potentially a vector for [cross-site-scripting (XSS)](/en-US/docs/Web/Security/Attacks/XSS) attacks.
13
+
>
14
+
> You can mitigate this risk by always passing {{domxref("TrustedScript")}} objects instead of strings and [enforcing trusted types](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types).
15
+
>
16
+
> See [Security considerations](#security_considerations) for more information.
17
+
18
+
The **`Function()`** constructor creates {{jsxref("Function")}} objects.
19
+
Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues as {{jsxref("Global_Objects/eval", "eval()")}}. However, unlike `eval` (which may have access to the local scope), the `Function` constructor creates functions which execute in the global scope only.
- : Names to be used by the function as formal argument names. Each must be a string that corresponds to a valid JavaScript parameter (any of plain [identifier](/en-US/docs/Glossary/Identifier), [rest parameter](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), or [destructured](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring) parameter, optionally with a [default](/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)), or a list of such strings separated with commas.
50
+
- : {{domxref("TrustedScript")}} instances or strings specifying names to be used by the function as formal argument names.
51
+
The value must correspond to a valid JavaScript parameter (any of plain [identifier](/en-US/docs/Glossary/Identifier), [rest parameter](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), or [destructured](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring) parameter, optionally with a [default](/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)), or a list of such strings separated with commas.
42
52
43
-
As the parameters are parsed in the same way as function expressions, whitespace and comments are accepted. For example: `"x", "theValue = 42", "[a, b] /* numbers */"` — or `"x, theValue = 42, [a, b] /* numbers */"`. (`"x, theValue = 42", "[a, b]"` is also correct, though very confusing to read.)
53
+
As the parameters are parsed in the same way as function expressions, whitespace and comments are accepted.
(`"x, theValue = 42", "[a, b]"` is also correct, though very confusing to read.)
44
56
45
57
-`functionBody`
46
-
- : A string containing the JavaScript statements comprising the function definition.
58
+
- : A {{domxref("TrustedScript")}} or a string containing the JavaScript statements comprising the function definition.
59
+
60
+
### Exceptions
61
+
62
+
- {{jsxref("SyntaxError")}}
63
+
- : Function parameter arguments can't be evaluated as valid identifiers, or the `functionBody` can't be parsed as a script.
64
+
- {{jsxref("TypeError")}}
65
+
- : Any parameter is a string when [Trusted Types](/en-US/docs/Web/API/Trusted_Types_API) are [enforced by a CSP](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) and no default policy is defined.
66
+
67
+
The method also throws any exception that occurs during evaluation of the code.
47
68
48
69
## Description
49
70
@@ -85,8 +106,41 @@ new Function("/*", "*/) {");
85
106
// Doesn't become "function anonymous(/*) {*/) {}"
86
107
```
87
108
109
+
### Security considerations
110
+
111
+
The method can be used to execute arbitrary input passed to any parameter.
112
+
If the input is a potentially unsafe string provided by a user, this is a possible vector for [Cross-site-scripting (XSS)](/en-US/docs/Web/Security/Attacks/XSS) attacks.
113
+
For example, the following example assumes the `untrustedCode` was provided by a user:
Websites with a [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/Guides/CSP) that specifies [`script-src`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/script-src) or [`default-src`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/default-src) will prevent such code running by default.
121
+
122
+
If you must allow the scripts to run via `Function()` you can mitigate these issues by always assigning {{domxref("TrustedScript")}} objects instead of strings, and [enforcing trusted types](/en-US/docs/Web/API/Trusted_Types_API#using_a_csp_to_enforce_trusted_types) using the [`require-trusted-types-for`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/require-trusted-types-for) CSP directive.
123
+
This ensures that the input is passed through a transformation function.
124
+
125
+
To allow `Function()` to run, you will additionally need to specify the [`trusted-types-eval` keyword](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#trusted-types-eval) in your CSP `script-src` directive.
126
+
127
+
The [`unsafe-eval`](/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy#unsafe-eval) keyword also allows `Function()`, but is much less safe then `trusted-types-eval` because it would allow execution even on browsers that do not support trusted types.
128
+
129
+
For example, the required CSP for your site might look like this:
The behavior of the transformation function will depend on the specific use case that requires a user provided script.
136
+
If possible you should lock the allowed scripts to exactly the code that you trust to run.
137
+
If that is not possible, you might allow or block the use of certain functions within the provided string.
138
+
88
139
## Examples
89
140
141
+
Note that these examples omit the use of trusted types for brevity.
142
+
For code showing the usual approach, see [Using `TrustedScript`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#using_trustedscript) in `eval()`.
143
+
90
144
### Specifying arguments with the Function constructor
91
145
92
146
The following code creates a `Function` object that takes two arguments.
@@ -147,6 +201,7 @@ sayHello("world");
147
201
148
202
## See also
149
203
204
+
-[Using the function constructor](/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#using_the_function_constructor) in `eval()`
0 commit comments