Suggest an editImprove this articleRefine the answer for “Why eval is dangerous”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`eval()` executes a string as ordinary JavaScript code in the current scope.** That is exactly why it is avoided: it runs any text you pass it, including malicious user input (XSS and injections), it is slow because the engine cannot optimise code it does not know in advance, it breaks scoping (it can create or overwrite surrounding variables) and it makes the code unpredictable to read and to debug. There is almost always a safer replacement: `JSON.parse()` for JSON, key access `obj[prop]` instead of string concatenation, a map of functions instead of a dynamic call. ```javascript // bad const obj = eval('(' + jsonStr + ')'); // good const obj = JSON.parse(jsonStr); ``` **Key point:** `eval()` turns data into code, so any uncontrolled string becomes a full program running with your application's privileges.Shown above the full answer for quick recall.Answer (EN)Image**`eval()` is a built in function that takes a string and makes the JavaScript engine execute it as ordinary code.** It is one of the most dangerous and most disputed functions in the language, because it erases the boundary between data and code, so it should almost always be replaced with something safer. ## Theory ### TL;DR - `eval(str)` runs the contents of the string `str` as JavaScript code and returns the value of the last expression. - The main problem is security: an uncontrolled string means arbitrary code execution, XSS and injections. - Performance drops, because the engine cannot analyse and optimise such code in advance (JIT is blocked). - `eval()` runs in the current scope, so it can create and overwrite the variables around it. - Almost every real task has a replacement: `JSON.parse()`, key access `obj[prop]`, a map of functions, `Function()` in a controlled case. ### Quick example ```javascript eval("console.log('Hello from eval!')"); // output: Hello from eval! const x = 10; const y = 5; console.log(eval('x + y')); // 15 ``` `eval` "understands" that the string `'x + y'` is an expression, evaluates it in the current scope and returns the result. ### What eval actually does `eval()` does not parse a formula and has no sandbox of its own: it hands the string to the very same engine that runs the rest of your code, with the very same privileges. Example 1, evaluating an expression: ```javascript const x = 10; const y = 5; console.log(eval('x + y')); // 15 ``` Example 2, creating variables (dangerous): ```javascript eval('var z = 100;'); console.log(z); // 100 ``` The problem is that `z` is created in the current scope and may overwrite existing values. Example 3, dynamic code (bad practice): ```javascript function runCode(code) { eval(code); } runCode("alert('running arbitrary code')"); ``` This executes any code passed as a string. If that string came from a user, you get an XSS attack or a full takeover of the application. ### Security risk (XSS and injections) `eval()` executes any code it is given, including malicious code typed in by a user or an attacker. ```javascript const userInput = "alert('pwned')"; eval(userInput); // runs straight away in the browser ``` Instead of `alert` that code could read `document.cookie`, `localStorage` or a session token and send them to a third party server. This is a direct path to XSS and data leaks. That is why Content Security Policy blocks `eval()` by default unless `unsafe-eval` is allowed. ### Worse performance Code inside `eval()` runs more slowly, because the engine cannot optimise it: it does not know in advance what will be there. Every `eval()` call forces the engine to parse and interpret the string again, and a function that contains `eval()` often loses JIT optimisations entirely, because the engine cannot prove which variables it uses. ### It breaks scoping Code inside `eval()` can create or change variables of the current context, which makes the program unpredictable and hard to debug. ```javascript let a = 10; eval('a = 99;'); console.log(a); // 99, the value changed "from the inside" ``` In strict mode (`'use strict'`) the situation is a little better: `eval()` gets its own scope for declarations, so a `var` inside it no longer leaks out. It can still read and overwrite existing variables though. ### Hard to read and to maintain `eval()` makes the code "magic": until it runs, you do not know what will be executed. Linters and static analysis see nothing inside the string, editor autocomplete and symbol renaming do not work, and stack traces point at generated code instead of a readable place in a file. ### Safe alternatives | Task | What to use instead | | --- | --- | | Evaluate a mathematical expression | `Function()` or a ready made expression parser | | Parse JSON | `JSON.parse()` | | Run dynamic code from a known set of functions | An object with a map of functions | | Read a property by name | `obj[propName]`, not `eval('obj.' + propName)` | Replacement examples. Bad: ```javascript eval("user.name = 'Tim'"); ``` Good: ```javascript user['name'] = 'Tim'; ``` Bad: ```javascript const obj = eval('(' + jsonStr + ')'); ``` Good: ```javascript const obj = JSON.parse(jsonStr); ``` Bad: ```javascript eval('sum(5, 10)'); ``` Good: ```javascript const actions = { sum: (a, b) => a + b }; actions['sum'](5, 10); ``` ### Common mistakes - Believing `new Function(...)` is safe. It also compiles a string into code, just in the global scope, so for untrusted input it is just as dangerous. - Using `eval()` to parse JSON. It is both slower and unsafe; `JSON.parse()` exists exactly for this. - Building a property name as a string: `eval('obj.' + key)` instead of `obj[key]`. The second version is shorter, faster and safe. - Thinking that sanitising the string makes `eval()` safe. Reliably escaping arbitrary JavaScript is practically impossible. - Forgetting the hidden forms of eval: a string as the first argument of `setTimeout('doWork()', 100)` is executed the same way. - Being surprised that `eval()` does not work in production: a CSP without `unsafe-eval` blocks it, and that is correct behaviour. ### Quick recap | Aspect | Verdict | | --- | --- | | What it does | Executes a string as JavaScript code | | Security | Very dangerous: XSS and injections | | Performance | Slow | | Debugging | Hard | | Optimisation | Blocks JIT | | When to use | Only in very rare cases, when the string is fully under your control |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.