Я пишу код JavaScript для анализа вводимых пользователем функций (для функций, подобных электронной таблице). Проанализировав формулу, я конвертирую мог в JavaScript и запускаю на нем eval(), чтобы получить результат.
Однако я всегда уклонялся от использования eval(), если я могу избежать этого, потому что это зло (и, правильно или ошибочно, я всегда думал, что это еще более зло в JavaScript, потому что код, который нужно оценить, может быть изменен Пользователь).
Итак, когда его можно использовать?
@Sean - и JQuery, и Prototype используют eval (JQuery использует его через новую функцию)
@plodder - Откуда вы берете информацию? jQuery использует собственный JSON.parse () с версии 1.4 (еще в 1/2010)! Смотрите сами: code.jquery.com/jquery-1.4.js
@ ken, Шон, он использует JSON.parse если это доступно, это не так для IE <= 7
@tobyodavies - хороший аргумент, за исключением того, что IE <= 7 вводит в заблуждение, поскольку ЛЮБОЙ браузер старше нескольких лет не будет иметь собственного объекта JSON. и я хотел сказать, что библиотеки JS не поддерживают предпочитатьeval() .... это просто резерв для браузеров наследие.
@ken, тоже хороший аргумент, однако IE6 и IE7 все еще очень широко используются, я бы назвал их старыми, не уверен в наследии - они, к сожалению, далеки от мертвых. определенно они не предпочитают это, но они используют его в некоторых ситуациях, поэтому они считают, что это достаточно безопасно с некоторыми ограничениями.
Еще одно обсуждение этой темы, более ориентированное на javascript, находится на stackoverflow.com/questions/4812288/….
@Tomas: ирония в том, что json2.js использует eval для анализа JSON
@tobyodavies, вау, это интересно, учитывая, что Дуглас критикует это. По крайней мере, есть серьезные проверки безопасности.
@Tomas, +1. Фактически, вы не можете использовать eval для правильного анализа всех строк JSON. JSON.parse(' "\u2028" ') работает, но eval(' "\u2028" ') не работает с исключением, потому что U + 2028 является новой строкой JavaScript, но разрешен в JSON без экранирования.
Использование eval может раскрыть код реализации вашей библиотеки, потому что он запускается из закрытия. Падение производительности также велико, потому что он каждый раз анализирует и компилирует. С конструктором Function этого можно избежать. Конструктор Function запускается при глобальном замыкании независимо от того, где он вызывается. Если вы планируете вызывать эту функцию несколько раз, она может стать «горячей», и движок JavaScript оптимизирует ее. И поскольку он возвращает объект функции, вы можете сохранить его в кеше, чтобы ограничить вызовы конструктора Function.
@tobyodavies Верно, однако Крокфорд говорит не используйте json2.js, если вам не нужна поддержка IE 8.
@jkdev Когда этот вопрос был задан, IE8 был доминирующим браузером, IE9 едва исполнился год. И Крокфорд добавил этот дискламер всего 2 недели назад (почти через 3 года после моего последнего комментария)
Вау, всего 2 недели назад? Я этого не знал.
Я понимаю точку зрения Крокфорда о рисках оценки вредоносного кода, встроенного в JSON. Как говорит @TMS, в json2.js есть проверки безопасности для защиты от этого.
@jkdev - по сути, вы пропустили, что Крокфорд говорит не использовать этот файл потому что JSON стал встроенной функцией JavaScript. AFAIK, в наши дни вы являются используете [эквивалентную функциональность]; но вы оставляете детали реализации на усмотрение поставщика языка.
@ToolmakerSteve json2.js: Вы правы в том, что с точки зрения пользователя не имеет значения, как JSON.parse () реализован под капотом. IE8 не имеет встроенного объекта JSON, поэтому вы должны использовать json2.js Крокфорда как более безопасную альтернативу eval, использующему JSON в своем коде. Это почти все, что нужно сделать.
«анализировать введенные пользователем функции (для функциональности, подобной электронной таблице)» подсказывает мне, что большая часть озабоченности по поводу eval здесь необоснованна. Предположим, что функция не сохраняется в БД, какой вред может нанести функция javascript на уровне одностраничного пользователя? Взламывает собственные данные? Если сохраняется и не передается, опять же, проблема относится к пользователю. Сохраняются и передаются (или просматриваются другими), да, у вас есть вектор XSS-инъекции.
eval всегда зло. Период исключений не существует. Если вы хотите оценить код, используйте window.Function. Конечно, есть случаи, когда вы можете делать с eval вещи, которые нельзя сделать иначе, но это незаконные варианты использования, которые никогда не должны выполняться каким-либо уважающим себя кодировщиком.
Mozilla ясно дает понять: Никогда не используйте eval!
Не забывайте, что eval несовместим со всеми инструментами, которые вы можете придумать, ESLint, Prettier, UglifyJS, большинством редакторов / функций IDE ... и вашим коллегам это не понравится, если они будут профессиональными. Поиск хитрого способа сделать что-то может показаться умным для решения немедленной проблемы, но это не в долгосрочной перспективе.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Когда вы доверяете источнику.
В случае JSON более или менее сложно вмешаться в источник, потому что он исходит от веб-сервера, которым вы управляете. Пока сам JSON не содержит данных, загруженных пользователем, использование eval не является серьезным недостатком.
Во всех остальных случаях я бы приложил все усилия, чтобы убедиться, что предоставленные пользователем данные соответствуют моим правилам, прежде чем передавать их в eval ().
Строку json всегда следует проверять на соответствие грамматике json, прежде чем использовать ее в eval (). Таким образом, строка json «{foo: alert ('XSS')}» не пройдет, поскольку «alert ('XSS')» не является правильным значением.
Или когда среда безопасна.
Но можно ли действительно доверять источнику, если вы используете протокол, уязвимый для атак типа «злоумышленник в середине»?
Что ж, тогда используйте HTTPS. OTOH: человек посередине не является типичным сценарием атаки для разнообразных веб-приложений, в отличие от межсайтового скриптинга.
eval также не будет правильно анализировать все допустимые строки JSON. Например, JSON.parse(' "\u2028" ') === "\u2028", но eval(' "\u2028" ') вызывает исключение, потому что U + 2028 - это новая строка в JavaScript, но это не новая строка в отношении JSON.
@Justin - если протокол скомпрометирован, ну, обычно начальная загрузка страницы будет отправлена по тому же протоколу, и тогда это спорный вопрос, потому что клиент уже настолько скомпрометирован, насколько это возможно.
Красиво сказано @Tomalak, я прямо сейчас упомянул об этом в своем ответе! Потрясающий!
«В случае JSON более или менее сложно вмешаться в исходный код, потому что он исходит от веб-сервера, которым вы управляете». Если вы не создаете службу REST API в nodejs. И даже если вы контролируете ситуацию, вы вводите уязвимость, которая становится идеальной отправной точкой для «безопасных» пользовательских сеансов после того, как доверенный сервер окажется скомпрометированным. Хакеры преуспевают в такой наивности. К счастью, сейчас есть хорошие альтернативы eval.
Node.js или что-то еще на стороне сервера абсолютно не к чему. делать с этим. В узле нет внутренней уязвимости. Когда ваш сервер скомпрометирован, совершенно неважно, используете ли вы JSON или что-то еще, поэтому ваш аргумент немного круговой.
Единственный случай, когда вам следует использовать eval (), - это когда вам нужно запускать динамический JS на лету. Я говорю о JS, который вы загружаете асинхронно с сервера ...
... И 9 раз из 10 вы могли бы легко избежать этого путем рефакторинга.
В настоящее время существуют другие (и более совершенные) способы асинхронной загрузки JavaScript с сервера: w3bits.com/async-javascript
Его можно использовать, если у вас есть полный контроль над кодом, передаваемым функции eval.
Если у вас есть полный контроль над тем, что вы передаете на eval, тогда возникает большой вопрос, когда имеет смысл использовать строку, а не настоящий JS?
@cHao Например, если у вас есть большое игровое приложение (5-10 МБ Javascript), лучше сначала создать простой быстро загружаемый AJAX-Preloader (1 КБ), который загружает большой основной скрипт при отображении файла Loading- Бар или что-то подобное. После загрузки вы можете использовать «eval (источник)» или лучше «новую функцию (источник)» для запуска загруженного сценария игрового приложения. Таким образом, пользователь может визуально увидеть, что Приложению требуется время для загрузки, пока игра не запустится. Без этого пользователь должен ждать загрузки всего приложения без какой-либо визуальной обратной связи.
@SammieFox Есть другие (и лучшие) способы сделать это, в первую очередь <script async = "true" src = "...">. См. Также: w3bits.com/async-javascript
Ответ - опасный совет; слишком многие разработчики ложно чувствуют, что все под контролем. Совет делает имеет смысл для программного обеспечения, которое больше не поддерживается активно. Но такое программное обеспечение следует считать мертвым.
Я предпочитаю следовать Совет Крокфорда для eval() и вообще избегать его. Даже способы, которые кажутся необходимыми, этого не делают. Например, setTimeout() позволяет передавать функцию, а не eval.
setTimeout(function() {
alert('hi');
}, 1000);
Даже если это источник доверенный, я не использую его, потому что код, возвращаемый JSON, может быть искажен, что в лучшем случае может сделать что-то шаткое, в худшем - выявить что-то плохое.
Каким образом успешный вызов веб-сервера приведет к искаженному результату (несмотря на ошибки в коде веб-сервера, генерирующего JSON)?
Я думаю, что ошибки в форматере JSON на стороне сервера, безусловно, являются проблемой. Зависит ли ответ сервера от любого текста, отправленного пользователем? Тогда вам нужно следить за XSS.
Если ваш веб-сервер не аутентифицирован через HTTPS, вы можете пострадать от какой-то атаки типа «человек посередине», когда другой хост перехватывает запрос и отправляет свои собственные данные.
Если кто-то может выполнить атаку «человек посередине», он легко сможет внедрить что угодно в ваши скрипты.
Вы вообще не должны полагаться на свой код javascript ... Вы не полагаетесь ни на что, что работает на стороне клиента ... Если кто-то атакует "человек посередине", зачем ему связываться с вашими объектами json? Он может обслуживать вам другую веб-страницу и разные файлы js ...
Мне лично не нравится аргумент «всегда есть другие способы сделать это». Например, вы также можете сказать, что всегда есть способы избежать объектно-ориентированного программирования. Это не значит, что это не лучший вариант. Если вы понимаете eval и его опасности, он может стать отличным инструментом для использования в правильных ситуациях.
Как можно было бы написать что-то вроде редактора "Tryit" на w3schools, Stack Snippets и т. д. Без eval?
Только во время тестирования, если возможно. Также обратите внимание, что eval () намного медленнее, чем другие специализированные оценщики JSON и т. д.
eval() - это не зло. Или, если это так, это зло так же, как отражение, файловый / сетевой ввод-вывод, многопоточность и IPC являются «злом» в других языках.
Если, для вашей цели, eval() быстрее, чем ручная интерпретация, или делает ваш код более простым или понятным ... тогда вы должны его использовать. Если нет, то не следует. Просто как тот.
Одна из таких целей может заключаться в создании оптимизированного кода, который будет либо слишком длинным, либо слишком повторяющимся для написания вручную. То, что в LISP требует макроса.
Это настолько общий совет, что его можно применить буквально к любому существующему блоку кода. На самом деле это ничего не добавляет к этому вопросу; в частности, это не помогает никому, приходящему сюда, определять, является ли их конкретное использование проблематичным или нет.
Быстрее, проще, понятнее ... Этот ответ недостаточно хорошо описывает последствия для безопасности.
Нет причин не использовать eval (), если вы можете быть уверены, что источник кода исходит от вас или реального пользователя. Несмотря на то, что он может манипулировать тем, что отправляется в функцию eval (), это не проблема безопасности, потому что он может манипулировать исходным кодом веб-сайта и, следовательно, может изменять сам код JavaScript.
Итак ... когда не использовать eval ()? Eval () не следует использовать только тогда, когда есть вероятность, что третья сторона может его изменить. Например, перехват соединения между клиентом и вашим сервером (но если это проблема, используйте HTTPS). Вы не должны использовать eval () для анализа кода, написанного другими, например, на форуме.
Re: «Нет причин не использовать eval (), если вы можете быть уверены, что источник кода исходит от вас или от реального пользователя». Это предполагает, что есть один пользователь. Эта предпосылка не указана в ОП. Когда есть несколько пользователей, небрежный eval строки, составленной из содержимого одного пользователя, может позволить этому пользователю выполнить код в браузере другого пользователя.
@MikeSamuel, eval может выполнять код в браузере другого пользователя, я этого не слышал, вы пробовали это? Такого никогда не случалось в истории просмотра, вы можете показать нам пример?
@AkashKava, строка может исходить от одного пользовательского агента, храниться в базе данных, а затем передаваться другому браузеру, который ее использует eval. Так происходит все время.
@MikeSamuel база данных? где? кто обслуживает неправильную строку? Разве не виновата база данных на стороне сервера? Во-первых, EVAL не виноват в плохо написанном коде на стороне сервера. Используйте jsfiddle и покажите миру реальный пример, где он может причинить вред.
@AkashKava, я не понимаю твой вопрос. Мы не говорим о конкретном приложении, но о причинах не использовать eval. Насколько полезно винить сервер? Если кого и следует винить, так это злоумышленника. Независимо от вины, клиент, который не уязвим для XSS, несмотря на ошибки на сервере, лучше, чем клиент, который уязвим, при прочих равных.
@AkashKava Вам может понадобиться eval для делать jsfiddle.
«Нет причин ...» Неправильно. Этот ответ игнорирует производительность и ремонтопригодность.
Я хотел бы воспользоваться моментом, чтобы затронуть предпосылку вашего вопроса - что eval () - это "зло". Слово «зло», используемое людьми, владеющими языком программирования, обычно означает «опасный», или, точнее, «способный причинить большой вред простой на вид командой». Итак, когда можно использовать что-то опасное? Когда вы знаете, в чем опасность, и когда принимаете соответствующие меры предосторожности.
А теперь давайте посмотрим на опасности использования eval (). Вероятно, существует множество мелких скрытых опасностей, как и все остальное, но два больших риска - причина, по которой eval () считается злом, - это производительность и внедрение кода.
К твоему конкретному случаю. Насколько я понимаю, вы сами генерируете строки, поэтому, предполагая, что вы осторожны, чтобы не допустить генерации такой строки, как "rm -rf something-important", риск внедрения кода отсутствует (но помните, что очень очень сложно для обеспечить это в общем случае). Кроме того, я считаю, что если вы работаете в браузере, внедрение кода представляет собой довольно незначительный риск.
Что касается производительности, вам придется сопоставить ее с простотой кодирования. Я считаю, что если вы разбираете формулу, вы можете вычислить результат во время синтаксического анализа, а не запускать другой синтаксический анализатор (тот, который находится внутри eval ()). Но может быть проще написать код с помощью eval (), и падение производительности, вероятно, будет незаметным. Похоже, что eval () в этом случае не более зла, чем любая другая функция, которая могла бы сэкономить вам время.
Вы не решаете проблему кода, в котором используется eval, который трудно отлаживать.
Более полный ответ на этот вопрос есть здесь stackoverflow.com/questions/951373/when-is-eval-evil-in-php
Внедрение кода - очень серьезная проблема для javascript, если вас вообще беспокоят данные вашего пользователя. Внедренный код будет запускаться (в браузере), как если бы он пришел с вашего сайта, позволяя ему выполнять любые действия, которые пользователь мог бы выполнить вручную. Если вы разрешаете (стороннему) коду входить на вашу страницу, он может заказывать вещи от имени вашего клиента или изменять их граватар, или что-то еще, что они могут делать через ваш сайт. Будь очень осторожен. Позволить хакерам владеть вашими клиентами так же плохо, как позволить им владеть вашим сервером.
Если данные поступают с вашего сервера и созданы вами, разработчиком, нет никакого вреда в использовании eval (). Настоящий вред - верить всему, что вы читаете. Вы видите, как многие люди говорят, что eval () - это зло, и они понятия не имеют, почему, кроме того, что они где-то читали это.
@ Шон Макмиллан: Я хочу верить вам, но если кто-то собирается перехватить и изменить javascript, идущий на eval() с вашего сервера, он также может просто изменить источник страницы, а также взять под контроль информацию пользователя. . . Я не вижу разницы.
@ user27476 - Я согласен с тем, что если кто-то собирается анализировать строку, то можно продолжить и произвести вычисления. Я бы так поступил, но, может быть, это только я.
В Chrome вот некоторые сравнения производительности между прямым кодом, уровнем этого кода и Function (code) () (то же, что и eval): jsperf.com/eval-vs-parse-and-call/2
Re "Внедрение кода - ... Опять же, у JavaScript в браузере такой проблемы нет" и "Кроме того, если вы работаете в браузере, я считаю, что внедрение кода представляет собой довольно незначительный риск". Вы предлагаете, чтобы внедрение кода в браузере не было проблемой? XSS входит в топ-3 уязвимостей в топ-10 списка OWASP несколько лет подряд.
@MikeSamuel, XSS работает только в том случае, если вы можете внедрить код в чужой браузер («Межсайтовый скриптинг (XSS) - это тип уязвимости компьютерной безопасности…, который позволяет злоумышленникам внедрять клиентский скрипт в веб-страницы, просматриваемые другими пользователями». Википедия) . Так что, если вы оцениваете код, который пользователь ввел на той же странице, ни вреда, ни фола. Если вы позволяете посетителям оставлять комментарии без предварительной обработки, вы открываете им возможность оставлять яйца кукушки.
@thirdender, что заставляет вас поверить, что строка, достигающая eval, не содержит символов, контролируемых другим пользователем? В исходном вопросе никогда не говорится, что электронную таблицу может просматривать только один пользователь.
@MikeSamuel, каждый случай нужно рассматривать отдельно. Вот почему я сказал, что важно дезинфицировать вводимые пользователем данные. Однако я считаю, что фраза «eval - это зло» сама по себе не соответствует действительности. Однако, если вы оказались в ситуации, когда считаете, что eval - ваше единственное решение, вам следует остановиться и подумать. Если этого можно избежать, вероятно, лучше сделать это, но не любой ценой. Кроме того, стоит отметить, что Дуглас Крокфорд (известный как «eval is evil») осуждает безблочные операторы, а операнды ++ / -- только на две страницы после eval (Javascript: хорошие моменты).
@thirdender, я думаю, вы меня путаете с кем-то, кто сказал: "eval - это зло".
«JavaScript в браузере не имеет этой проблемы, потому что программа в любом случае выполняется под собственной учетной записью пользователя» - это не полностью отражает проблему с использованием eval. Если сценарий, введенный одним пользователем, использует eval () для другого, это может нанести серьезный ущерб. И ответ, похоже, не заботится об этом.
На самом деле проблема не в eval, а в том, как вы настраиваете взаимодействие с пользователем. Пользователи должны были передать им очищенные строки (если есть какой-либо контент, созданный пользователем). Я действительно не понимаю, почему это ошибка eval, конечно, есть опасность его использования, но это не имеет ничего общего с eval, если вы разрешаете пользовательский контент, ваши пользователи могут делать много других злых вещей, помимо злоупотребления плохо защищенным использованием eval.
@bobobobo: на самом деле eval() может помочь в отладке. Мой пост под stackoverflow.com/questions/197769/…
При внедрении кода: связанный с этим риск зависит от того, как именно используется функция eval. eval("alert('hello')") представляет собой не больший риск, чем alert('hello'), потому что в обоих случаях злоумышленнику потребуется изменить источник, чтобы что-то изменить. Однако если что-то вроде eval ("users ['" + username + "']") может быть чрезвычайно опасным, потому что злоумышленнику просто нужно придумать умное имя пользователя, и он сможет запускать код от имени других пользователей. tl; dr eval - это не зло. eval + плохое программирование - это зло.
«У JavaScript в браузере нет такой проблемы, потому что программа в любом случае выполняется под собственной учетной записью пользователя». Если только в JavaScript не указано «установить это вредоносное ПО на машину» и у пользователя есть на это права.
У меня есть приложение только для внутреннего использования, в котором я подумал об использовании eval () для создания функций на основе предоставленного мной файла JSON. Функции влияют только на включение, обнуление и т. д. Полей пользовательского интерфейса, поэтому даже если JSON будет скомпрометирован, это приведет к поломке пользовательского интерфейса. Если они также изменят файл .js, то у них уже будет полный контроль. Было бы намного меньше кода ... Оглядываясь назад, я должен был это сделать.
Производительность: вы можете просто заставить eval создать функцию, которая будет выполнять эту работу - код будет скомпилирован только один раз (или использовать new Function).
Чуваку, говорящему о внедрении кода, который получил 40+ голосов ... нет. Любой, кто имеет доступ к вашему сайту до того, как пользователь коснется его, может запустить код на вашем сайте и может сбросить свои собственные js-файлы, которые влияют на данные пользователя без вашего разрешения, и для этого не требуется eval. Любой, кто вводит js ПОСЛЕ того, как пользователь прикоснулся к нему, ВСЕГДА может разместить свои js на вашей странице без eval. Это похоже на то, что вы делаете с расширениями Chrome, используя сценарии содержимого, а также с браузерами без головы или простыми старыми инструментами разработчика. Дерьмо, которое ты можешь творить, бесконечно. Я все еще жду, чтобы увидеть хоть один пример клиентского js eval evil
@AaronLoften Хакеры - не боги. У них нет вашего пароля администратора. Они молча очищают ваш сайт на предмет крошечных обрывков информации и слабых мест. Они могли даже использовать социальную инженерию, чтобы заполнить пробелы. Никакая информация не оказывает серьезного воздействия, но все вместе это может стать настоящим нарушением безопасности. Инъекции (включая eval) - это вишенка на торте; это завершает атаку. Google, Facebook, а также крупные интернет-магазины и банки ежедневно сталкиваются с этим. Почему вы не читаете об этом больше? Потому что компании не любят выплескивать душу.
Интересно, почему никто не поднял это? Использование eval() ограничивает JS-движки от выполнения какой-либо оптимизации для этого блока кода, которую они обычно делают во время компиляции, поскольку код eval() может быть оценен только во время выполнения, поэтому браузерные движки будут пессимистами и просто не будут через процесс оптимизации, так как он ничего не может предсказать. Подробнее -> github.com/getify/You-Dont-Know-JS/blob/2nd-ed/scope-closure s /…
Я видел, как люди выступают за то, чтобы не использовать eval, потому что это зло, но я видел, что те же люди используют Function и setTimeout динамически, поэтому они используют eval под капотами: D
Кстати, если ваша песочница недостаточно уверена (например, если вы работаете на сайте, который разрешает внедрение кода), eval - последняя из ваших проблем. Основное правило безопасности заключается в том, что ввод все является злом, но в случае JavaScript выравнивать сам JavaScript может быть злом, потому что в JavaScript вы можете перезаписать любую функцию, и вы просто не можете быть уверены, что используете настоящую, так что, если вредоносный код запускается раньше вас, вы не можете доверять ни одной встроенной функции JavaScript: D
Теперь эпилог к этому посту:
Если вам нужен В САМОМ ДЕЛЕ (80% времени требуется eval - НЕТ) и вы уверены в том, что делаете, просто используйте eval (или лучшую функцию;)), замыкания и ООП покрывают 80/90% случай, когда eval можно заменить с использованием другой логики, остальное - это динамически сгенерированный код (например, если вы пишете интерпретатор) и, как вы уже сказали, оценка JSON (здесь вы можете использовать безопасную оценку Крокфорда;))
И как указал сам Крокфорд, текущие веб-браузеры имеют встроенную функцию JSON.parse.
Если это действительно необходимо, eval - это не зло. Но в 99,9% случаев использования eval, с которыми я сталкиваюсь, требуется нет (не включая материал setTimeout).
Для меня зло - это не производительность или даже не проблема безопасности (ну, косвенно и то и другое). Такое ненужное использование eval только усложняет обслуживание. Инструменты рефакторинга отброшены. Искать код сложно. Непредвиденных эффектов от этих достижений - легион.
eval не требуется для setTimeout. Вы также можете использовать здесь ссылку на функцию.
Я считаю, что eval - очень мощная функция для клиентских веб-приложений и безопасная ... Так же безопасна, как JavaScript, а это не так. :-) Проблемы безопасности - это, по сути, проблема на стороне сервера, потому что теперь с помощью такого инструмента, как Firebug, вы можете атаковать любое приложение JavaScript.
Использование eval должно быть защищено от XSS-атак, что не всегда легко исправить.
Microsoft объясняет, почему eval () работает медленно в их браузере, в блоге IE, Рекомендации по производительности IE + JavaScript, часть 2: Неэффективность кода JavaScript.
eval редко бывает правильным выбором. Хотя может быть множество случаев, когда вы можете выполнить то, что вам нужно, объединив сценарий и запустив его на лету, в вашем распоряжении обычно есть гораздо более мощные и удобные в обслуживании методы: нотация ассоциативного массива (obj["prop"] - это то же самое, что и obj.prop), замыкания, объектно-ориентированные методы, функциональные методы - используйте их вместо этого.
Что касается клиентского скрипта, я думаю, что вопрос безопасности - спорный. Все, что загружается в браузер, может быть изменено и должно рассматриваться как таковое. Существует нулевой риск при использовании оператора eval (), когда есть гораздо более простые способы выполнения кода JavaScript и / или манипулирования объектами в DOM, такими как строка URL-адреса в вашем браузере.
javascript:alert("hello");
Если кто-то хочет манипулировать своим DOM, я говорю, уходите прочь. Ответственность за безопасность для предотвращения любого типа атак всегда должна лежать на серверном приложении, точка.
С прагматической точки зрения нет никакой пользы от использования eval () в ситуации, когда все можно сделать иначе. Однако есть особые случаи, когда СЛЕДУЕТ использовать eval. В таком случае это определенно можно сделать без риска взорвать страницу.
<html>
<body>
<textarea id = "output"></textarea><br/>
<input type = "text" id = "input" />
<button id = "button" onclick = "execute()">eval</button>
<script type = "text/javascript">
var execute = function(){
var inputEl = document.getElementById('input');
var toEval = inputEl.value;
var outputEl = document.getElementById('output');
var output = "";
try {
output = eval(toEval);
}
catch(err){
for(var key in err){
output += key + ": " + err[key] + "\r\n";
}
}
outputEl.value = output;
}
</script>
<body>
</html>
Re "Нет никакого риска в использовании оператора eval (), когда есть гораздо более простые способы выполнения javascript и / или манипулирования объектами в DOM". Внедрение кода представляет собой проблему, когда один пользователь может ввести код, который затем запускается в браузере другого пользователя. Консоли браузера сами по себе не позволяют одному пользователю запускать код в браузере другого пользователя, поэтому они не имеют значения при принятии решения о том, стоит ли защищаться от внедрения кода.
Разве <head></head> не требуется, даже если он пуст?
Этот ответ полностью игнорирует риски XSS.
Возьмем настоящих людей:
В каждом крупном браузере теперь есть встроенная консоль, которую ваш потенциальный хакер может использовать в изобилии для вызова любой функции с любым значением - зачем им использовать выражение eval - даже если бы они могли?
Если для компиляции 2000 строк JavaScript требуется 0,2 секунды, какова моя потеря производительности, если я оцениваю четыре строки JSON?
Даже объяснение Крокфорда «eval - это зло» слабо.
eval is Evil, The eval function is the most misused feature of JavaScript. Avoid it
Как мог бы сказать сам Крокфорд: «Подобные утверждения имеют тенденцию вызывать иррациональный невроз. Не покупайтесь на это».
Понимание eval и знание того, когда он может быть полезен, гораздо важнее. Например, eval - разумный инструмент для оценки ответов сервера, сгенерированных вашим программным обеспечением.
Кстати: Prototype.js вызывает eval напрямую пять раз (в том числе в evalJSON () и evalResponse ()). jQuery использует его в parseJSON (через конструктор функций).
JQuery использует встроенную в браузер функцию JSON.parse, если она доступна (что намного быстрее и безопаснее), используя eval только как резервный механизм. Утверждение «eval - это зло» является достаточно хорошим ориентиром.
Re "Каждый крупный браузер теперь имеет встроенную консоль ...". Внедрение кода представляет собой проблему, когда один пользователь может ввести код, который затем запускается в браузере другого пользователя. Консоли браузера сами по себе не позволяют одному пользователю запускать код в браузере другого пользователя, поэтому они не имеют значения при принятии решения о том, стоит ли защищаться от внедрения кода.
«Каждый крупный браузер теперь имеет встроенную консоль ... зачем им использовать выражение eval?» - Вы ошибаетесь. Предлагаю вам отредактировать ответ. Возможность одного пользователя внедрить код, который может работать в другом браузере, является серьезной проблемой. И именно здесь вам нужно стать настоящим.
Кто вообще такой Крокфорд? Вы правы, злоумышленник может использовать любой инструмент HTTP-выщелачивания, чтобы имитировать браузер и делать что угодно, ему не нужен EVAL.
@akkishore, я буду признателен, если вы приведете пример из реальной жизни, подтверждающий ваши чрезмерно заявленные утверждения.
@AkashKava DNS отравляет / MITM, перехватывает и редактирует данные eval () ed и ка-бум!
@akkishore, это не имеет ничего общего с EVAL, это означает, что вы не защитили свой DNS или прокси или что-то еще, помните больше, чем браузер, у злоумышленника есть много инструментов, чтобы нанести вред, кроме EVAL, написание таких слов ничего не доказывает, покажите мне рабочий код, а это зло в EVAL, делайте это на любом безопасном DNS. Если браузер или клиентская машина скомпрометированы, EVAL еще не является злом.
@AkashKava Давайте упростим. Предлагаете ли вы разработать наши API / интерфейсы для приема исполняемого кода в качестве входных данных, которые выполняются без проверки работоспособности? Для тех, кто говорит, что вы можете использовать консоль для вызова любых функций, обратите внимание, что закрытие, доступное для eval'ed кода, может быть недоступно для консоли, делайте то, что вы можете!
@akkishore, какой вред он может нанести браузеру? да, если это код на стороне сервера, например php или ruby на сервере или C# на сервере, тогда да, он должен быть проверен на безопасность. Допустим, все, что я наберу в этом поле для комментариев, будет оценено, какой вред это нанесет серверу переполнения стека? ничего такого. Это ваш серверный код, который должен быть безопасным, браузер в любом случае очень безопасен, поскольку он не предлагает никаких встроенных подключений в любой форме. В целом EVAL вне песочницы - зло, но внутри браузера в песочнице вреда нет.
@AkashKava, я думаю, что другие здесь намекнули на это, но eval действительно проблема. Атака с использованием межсайтовых сценариев (XSS) - это когда злоумышленник заставляет JS-код запускаться в контексте браузера другого пользователя. Вы думаете, что с этим делать? Они могут украсть ваш сеанс и выдать себя за вас на этом сайте. Они могут публиковать спам-комментарии. Они могут собирать вашу личную информацию. Представьте, что это произошло на веб-сайте банка: они могли украсть ваши номера счетов и остатки средств. Предлагаю вам прочитать en.wikipedia.org/wiki/Cross-site_scripting.
@BrianDonovan, как это возможно сейчас? Какой браузер позволяет запускать js в контексте другого домена. Статья - история, только http Cookie скрывает сессию и куки от js. Все основные браузеры очень хорошо защищают личную информацию. Дело в том, что мало знаний опаснее. Вы можете не использовать EVAL и не применять http только к более вредоносным файлам cookie. Отказ от использования EVAL не решит никаких проблем, безопасность вашего сервера должна быть строгой, независимо от EVAL.
@AkashKava, Безопасность сервера важна, но это не единственная часть истории. Кроме того, мы не говорим о запуске кода в контексте другого домена, мы говорим о внедрении HTML в браузер другого пользователя в том же домене. Например, если вы управляете сайтом, который позволяет людям публиковать комментарии, используя подмножество HTML, вы должны быть очень осторожны, чтобы не разрешить такой HTML: <div onclick = "malicious code">. Это не просто. Если вы разрешите запуск этого HTML-кода в браузере другого пользователя, злоумышленник может делать плохие вещи, как я упоминал в своем последнем комментарии.
@AkashKava Что вы не понимаете, так это того, что если я отправлю javascript в поле для комментариев, и этот javascript попадет в базу данных. Когда другой пользователь просматривает этот комментарий (в который я вставляю javascript), eval принимает этот javascript при его рендеринге и оценивает его с помощью интерпретатора, в результате чего мой встроенный javascript запускается в браузере другого пользователя. Делая это, я могу собирать всевозможную информацию. Их имя пользователя, их идентификатор пользователя в базе данных, их адрес электронной почты и т. д. Это не сложный ответ, если бы у вас был Googled XSS, вы бы через 10 секунд увидели, почему это проблема.
Этот ответ настолько невероятно неправильный, что я шокирован, что он вообще получил какие-то положительные голоса. Eval JSON? Ты не в своем уме? Вы когда-нибудь слышали о парсерах или внедрении кода?
@KyleRichter, вот и вы, когда JavaScript превращается в базу данных, это прекрасный пример вашей слабой безопасности на стороне сервера. Злоумышленник может легко использовать что угодно, кроме браузера, даже простой curl может отправить JavaScript в базу данных. Опасен не eval, это ваша слабая защита позволяет коду попасть в базу данных, что вызывает все проблемы, которые, кстати, злоумышленник может обойтись даже без eval.
@AkashKava Я не знаю, почему я даже удостоен этого ответом, но это так. Javascript в строке сам по себе не вреден, но использование eval приведет к тому, что этот javascript будет ЗАПУСКАЕТСЯ, тогда как в противном случае он будет интерпретирован как строка, которая не будет проанализирована. Я не возражаю, что на стороне сервера должно происходить экранирование, однако использование eval - это просто ПРОСЬБА, чтобы кто-то нашел способ использовать это поле. Независимо от того, как вы это утверждаете, это ДЕЙСТВИТЕЛЬНО представляет угрозу безопасности и ЯВЛЯЕТСЯ плохой практикой. Период. Вот почему все здесь повторяют то, что я сказал о НЕ использовании eval.
@AkashKava Еще одна вещь. eval () полезен тогда и только тогда, когда вы можете ГАРАНТИРОВАТЬ, что ЕДИНСТВЕННЫЙ возможный ввод - это javascript, который сгенерировал ВАШЕ приложение. Но даже в этом случае это полезно только потому, что нет варианта ЛУЧШЕ. Prototype.js использовал eval, потому что это было единственное, что им было доступно для их требований, и они делали это там, где ЗНАЛИ, что целостность кода была чистой.
Этот ответ игнорирует всю концепцию межсайтового скриптинга.
Когда eval () в JavaScript не является злом?
Я всегда пытаюсь отговорить от использования eval. Почти всегда доступно более чистое и удобное в обслуживании решение. Оценка не нужен даже для парсинга JSON. Оценка добавляет к аду техобслуживания. Недаром его осуждают такие мастера, как Дуглас Крокфорд.
Но я нашел один пример, в котором использовался должно быть:
Например, у меня есть функция, которая создает для меня общий объект google.maps.ImageMapType, но мне нужно сообщить ей рецепт, как он должен создавать URL-адрес плитки из параметров zoom и coord:
my_func({
name: "OSM",
tileURLexpr: '"http://tile.openstreetmap.org/"+b+"/"+a.x+"/"+a.y+".png"',
...
});
function my_func(opts)
{
return new google.maps.ImageMapType({
getTileUrl: function (coord, zoom) {
var b = zoom;
var a = coord;
return eval(opts.tileURLexpr);
},
....
});
}
Похоже, его можно реорганизовать, чтобы не использовать eval () - tileURLexpr - это просто шаблон, поэтому разумное использование replace () сработает. Тем не менее, это напоминает мне пример, который я имел в виду, когда отправлял вопрос, который был связан с предоставлением пользователю возможности указать математическую формулу для оценки, аналогично функциональности электронных таблиц. Конечно, тогда я не упомянул об этом, потому что не хотел влиять на ответы!
tileURL: function (zoom, coord) { return 'http://tile.openstreetmap.org/' + b + '/' + a.x + '/' + a.y + '.png'; },
Когда вы анализируете структуру JSON с помощью функции синтаксического анализа (например, jQuery.parseJSON), она ожидает идеальной структуры файла JSON (каждое имя свойства заключено в двойные кавычки). Однако JavaScript более гибкий. Следовательно, вы можете использовать eval (), чтобы этого избежать.
Не используйте вслепую eval, особенно. при получении данных JSON из стороннего источника. См. JSON.Stringify без кавычек на свойствах? для правильного подхода к синтаксическому анализу «JSON без заключенных в кавычки имен».
Если он не использует двойные кавычки вокруг имен свойств, это может быть строковое представление литерала объекта, но это не JSON. JSON определяет имена свойств как string и определяет string как последовательность из нуля или более символов Юникода, заключенных в двойные кавычки с использованием экранирования обратной косой черты.
См. Статью Николаса Закаса - «eval () не зло, просто неправильно понят» nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderst ood
@vitmalina Из статьи Закаса: «Это может быть опасно, если вы принимаете вводимые пользователем данные и запускаете их через eval (). Однако, если ваш ввод не от пользователя, существует ли реальная опасность?» В этом и проблема. Как только ваш код выходит за рамки «привет, мир», быстро становится невозможным доказать, что вы не пропускаете пользовательский ввод в eval. В любом серьезном мультитенантном веб-приложении, когда десятки разработчиков работают над одной и той же кодовой базой, это недопустимо.
Eval дополняет компиляцию, которая используется при создании шаблонов кода. Под шаблонами я подразумеваю, что вы пишете упрощенный генератор шаблонов, который генерирует полезный код шаблона, который увеличивает скорость разработки.
Я написал фреймворк, в котором разработчики не используют EVAL, но используют наш фреймворк, и, в свою очередь, этот фреймворк должен использовать EVAL для создания шаблонов.
Производительность EVAL можно увеличить, используя следующий метод; вместо выполнения сценария вы должны вернуть функцию.
var a = eval("3 + 5");
Он должен быть организован как
var f = eval("(function(a,b) { return a + b; })");
var a = f(3,5);
Кеширование f, безусловно, повысит скорость.
Также Chrome позволяет очень легко отлаживать такие функции.
Что касается безопасности, использование eval или нет вряд ли будет иметь какое-либо значение,
Если ваша серверная безопасность достаточно надежна, чтобы кто-нибудь мог атаковать откуда угодно, вам не стоит беспокоиться о EVAL. Как я уже упоминал, если бы EVAL не существовало, у злоумышленников было бы множество инструментов для взлома вашего сервера, независимо от возможностей EVAL вашего браузера.
Eval подходит только для создания некоторых шаблонов для сложной обработки строк на основе того, что не используется заранее. Например, я предпочту
"FirstName + ' ' + LastName"
В отличие от
"LastName + ' ' + FirstName"
Как мое отображаемое имя, которое может быть взято из базы данных и не жестко запрограммировано.
Вы можете использовать функцию вместо eval - function (first, last) { return last + ' ' + first }.
Имена столбцов взяты из базы данных.
Угроза eval в основном другие пользователи. Допустим, у вас есть страница настроек, на которой вы можете указать, как ваше имя будет отображаться для других. Предположим также, что вы не очень ясно думали, когда писали это, поэтому в вашем поле выбора есть такие параметры, как <option value = "LastName + ' ' + FirstName">Last First</option>. Я открываю свои инструменты разработчика, меняю value параметра на alert('PWNED!'), выбираю измененный параметр и отправляю форму. Теперь, когда кто-то другой видит мое отображаемое имя, этот код запускается.
@cHao, тот, о котором вы говорите, является примером плохой безопасности на стороне сервера, сервер никогда не должен принимать данные, которые могут быть выполнены как код в любом браузере. И снова вы не смогли понять концепцию плохой безопасности на стороне сервера.
Вы можете ныть о безопасности на стороне сервера, если хотите, но вся суть eval заключается в выполнении кода, который не является частью написанного вами сценария. Если вам не нужна мощность для этого (а вы почти никогда этого не делаете), отказ от eval поможет предотвратить целую категорию проблем. Это хорошо, если ваш серверный код не идеален.
«Если ваша серверная безопасность достаточно надежна, чтобы кто-нибудь мог атаковать откуда угодно, вам не стоит беспокоиться о EVAL». Именно поэтому вы беспокоитесь о должен. Ни один сервер не защищен на 100%. Утечка паролей, социальная инженерия, озлобленные сотрудники, баги безопасности. Недостаточно, чтобы обыскать систему. Но если бы я мог обновить только одну запись в вашей базе данных, я бы выбрал исходную таблицу вашего строкового процессора. Возможная XSS-атака! Так работают хакеры. У них нет пароля администратора. Они находят крошечные слабые места, ни одна из которых не имеет реального значения. Но в совокупности их может быть достаточно, чтобы нанести реальный ущерб.
Мой пример использования eval: импорт.
Как это обычно делается.
var components = require('components');
var Button = components.Button;
var ComboBox = components.ComboBox;
var CheckBox = components.CheckBox;
...
// That quickly gets very boring
Но с помощью eval и небольшой вспомогательной функции он выглядит намного лучше:
var components = require('components');
eval(importable('components', 'Button', 'ComboBox', 'CheckBox', ...));
importable может выглядеть так (эта версия не поддерживает импорт конкретных элементов).
function importable(path) {
var name;
var pkg = eval(path);
var result = '\n';
for (name in pkg) {
result += 'if (name !== undefined) throw "import error: name already exists";\n'.replace(/name/g, name);
}
for (name in pkg) {
result += 'var name = path.name;\n'.replace(/name/g, name).replace('path', path);
}
return result;
}
+1 за идею, но у вас тут ошибка: .replace(/name/g, name).replace('path', path). Если name содержит строку "path", вы можете получить сюрпризы.
Объявление одной переменной для каждого свойства components - возможный запах кода; рефакторинг вашего кода может полностью устранить «проблему». Ваше текущее решение - просто синтаксический сахар. Если вы настаиваете на этом, я бы порекомендовал написать собственный препроцессор, который будет выполняться перед развертыванием. Это должно держать eval подальше от производственного кода.
Eval полезно для генерации кода, когда у вас нет макросов.
В качестве (глупого) примера, если вы пишете компилятор Brainfuck, вы, вероятно, захотите создать функцию, которая выполняет последовательность инструкций в виде строки и оценивает ее, чтобы вернуть функцию.
Либо вы пишете компилятор (который сохраняет, а не выполняет генерируемый код), либо вы пишете интерпретатор (где каждая инструкция имеет предварительно скомпилированную реализацию). eval тоже не подходит.
Если вы сгенерировали код javascript и хотели бы немедленно его выполнить (скажем, для повышения производительности по сравнению с прямой интерпретацией), это был бы вариант использования eval.
Хорошая точка зрения; Я видел пример в эта статья о Blockly. Я шокирован, что Google рекомендует eval, когда альтернатива (Функция) и быстрее (как объяснено в MDN), и более надежна (предотвращает непредсказуемые ошибки за счет лучшей изоляции между сгенерированным кодом и другим «вспомогательным» кодом на той же веб-странице).
При отладке в Chrome (v28.0.1500.72) я обнаружил, что переменные не привязаны к замыканиям, если они не используются во вложенной функции, производящей замыкание. Думаю, это оптимизация движка JavaScript.
НО: когда eval() используется внутри функции, которая вызывает закрытие, ВСЕ переменные внешних функций привязаны к закрытию, даже если они вообще не используются. Если у кого-то есть время проверить, может ли это быть вызвано утечкой памяти, оставьте мне комментарий ниже.
Вот мой тестовый код:
(function () {
var eval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is visible in debugger
eval("1");
})();
}
evalTest();
})();
(function () {
var eval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is NOT visible in debugger
var noval = eval;
noval("1");
})();
}
evalTest();
})();
(function () {
var noval = function (arg) {
};
function evalTest() {
var used = "used";
var unused = "not used";
(function () {
used.toString(); // Variable "unused" is NOT visible in debugger
noval("1");
})();
}
evalTest();
})();
Я хотел бы здесь отметить, что eval () не обязательно должен ссылаться на встроенную функцию eval(). Все зависит от названия функции. Таким образом, при вызове собственного eval() с псевдонимом (скажем, var noval = eval;, а затем во внутренней функции noval(expression);) оценка expression может завершиться ошибкой, когда он ссылается на переменные, которые должны быть частью замыкания, но на самом деле это не так.
Генерация кода. Недавно я написал библиотеку под названием Гипербары, которая устраняет разрыв между виртуальный дом и рули. Для этого он анализирует шаблон руля и конвертирует его в гипертекст. Гиперскрипт сначала создается в виде строки, и eval() перед ее возвратом превращает ее в исполняемый код. Я обнаружил, что eval() в этой конкретной ситуации является полной противоположностью зла.
В основном из
<div>
{{#each names}}
<span>{{this}}</span>
{{/each}}
</div>
К этому
(function (state) {
var Runtime = Hyperbars.Runtime;
var context = state;
return h('div', {}, [Runtime.each(context['names'], context, function (context, parent, options) {
return [h('span', {}, [options['@index'], context])]
})])
}.bind({}))
Производительность eval() не является проблемой и в подобной ситуации, потому что вам нужно только один раз интерпретировать сгенерированную строку, а затем многократно повторно использовать результат выполнения исполняемого файла.
Вы можете увидеть, как была достигнута генерация кода, если вам интересно здесь.
«Гиперскрипт сначала создается как строка (...)» Имеет смысл выполнить генерацию всего кода на этапе сборки, записать полученный гиперсрипт в отдельный исполняемый файл (.js), затем развернуть этот файл для тестирования и производство. Мне нравится, как вы используете генерацию кода. Просто eval является намеком на то, что некоторая ответственность, которая принадлежит времени компиляции, перешла во время выполнения.
На стороне сервера eval полезен при работе с внешними скриптами, такими как sql, Infxdb или mongo. Где настраиваемая проверка во время выполнения может быть выполнена без повторного развертывания ваших служб.
Например, служба достижений со следующими метаданными
{
"568ff113-abcd-f123-84c5-871fe2007cf0": {
"msg_enum": "quest/registration",
"timely": "all_times",
"scope": [
"quest/daily-active"
],
"query": "`SELECT COUNT(point) AS valid from \"${userId}/dump/quest/daily-active\" LIMIT 1`",
"validator": "valid > 0",
"reward_external": "ewallet",
"reward_external_payload": "`{\"token\": \"${token}\", \"userId\": \"${userId}\", \"amountIn\": 1, \"conversionType\": \"quest/registration:silver\", \"exchangeProvider\":\"provider/achievement\",\"exchangeType\":\"payment/quest/registration\"}`"
},
"efdfb506-1234-abcd-9d4a-7d624c564332": {
"msg_enum": "quest/daily-active",
"timely": "daily",
"scope": [
"quest/daily-active"
],
"query": "`SELECT COUNT(point) AS valid from \"${userId}/dump/quest/daily-active\" WHERE time >= '${today}' ${ENV.DAILY_OFFSET} LIMIT 1`",
"validator": "valid > 0",
"reward_external": "ewallet",
"reward_external_payload": "`{\"token\": \"${token}\", \"userId\": \"${userId}\", \"amountIn\": 1, \"conversionType\": \"quest/daily-active:silver\", \"exchangeProvider\":\"provider/achievement\",\"exchangeType\":\"payment/quest/daily-active\"}`"
}
}Которые затем позволяют,
Прямая инъекция объекта / значений через буквальную строку в json, полезна для создания шаблонов текстов
Может использоваться в качестве компаратора, например, мы создаем правила, как проверять квест или события в CMS.
Против этого:
Могут быть ошибки в коде и поломки в сервисе, если не полностью протестированы.
Если хакер может написать сценарий в вашей системе, вы в значительной степени облажались.
Один из способов проверить ваш скрипт - хранить хеш скриптов в безопасном месте, чтобы вы могли проверить их перед запуском.
Хороший. Когда я задал вопрос, я даже не думал о серверном JS.
Я думаю, что оправдание eval будет редкостью. Вы с большей вероятностью будете использовать его, думая, что он оправдан, чем использовать его, когда он на самом деле оправдан.
Проблемы безопасности наиболее известны. Но также имейте в виду, что JavaScript использует JIT-компиляцию, и это очень плохо работает с eval. Eval чем-то похож на черный ящик для компилятора, и JavaScript должен иметь возможность предсказывать код заранее (до некоторой степени), чтобы безопасно и правильно применять оптимизацию производительности и определение области видимости. В некоторых случаях влияние на производительность может даже повлиять на другой код вне eval.
Если вы хотите узнать больше: https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch2.md#eval
Если вы создали или обработали код eval, он никогда не будет зло.
eval - это зло, если он запущен на сервере с использованием ввода, отправленного клиентом, который был не создано разработчиком или был не продезинфицирован разработчиком.
eval - это не зло, если он запущен на клиенте, даже при использовании необработанного ввода, созданного клиентом.
Очевидно, что должен всегда дезинфицирует ввод, чтобы иметь некоторый контроль над тем, что потребляет ваш код.
Клиент может запускать любой произвольный код по своему усмотрению, даже если разработчик его не кодировал; Это верно не только для какие, но и для вызвать самому eval.
Eval - это не зло, им просто злоупотребляют.
Если вы создали код, входящий в него, или можете ему доверять, все в порядке. Люди продолжают говорить о том, что ввод пользователя не имеет значения для eval. Ну вроде ~
Если пользовательский ввод поступает на сервер, затем возвращается клиенту, и этот код используется в eval без очистки. Поздравляю, вы открыли ящик пандоры для отправки кому угодно пользовательских данных.
В зависимости от того, где находится eval, многие веб-сайты используют SPA, и eval может облегчить пользователю доступ к внутренним компонентам приложения, что в противном случае было бы нелегко. Теперь они могут создать фальшивое расширение для браузера, которое сможет записать этот eval и снова украсть данные.
Просто нужно понять, какой смысл использовать eval. Генерация кода не совсем идеальна, если можно просто создавать методы для подобных вещей, использовать объекты и т.п.
А теперь хороший пример использования eval.
Ваш сервер читает созданный вами файл swagger. Многие параметры URL создаются в формате {myParam}. Итак, вы хотите прочитать URL-адреса, а затем преобразовать их в строки шаблона без необходимости выполнять сложные замены, потому что у вас много конечных точек. Так что вы можете сделать что-то вроде этого.
Обратите внимание, это очень простой пример.
const params = { id: 5 };
const route = '/api/user/{id}';
route.replace(/{/g, '${params.');
// use eval(route); to do something
Большинство библиотек JSON фактически не используют eval под капотом именно для защиты от угроз безопасности.