Безопасность JavaScript или как написать безопасный код на JS. Тесное взаимодействие между JavaScript и DOM

Для Windows Phone 22.06.2020
Для Windows Phone

Разработка безопасных приложений на JavaScript - довольно сложное занятие. Но вполне выполнимое. В сегодняшней статье мы рассмотрим особенности JavaScript, из-за которых проблемы с безопасностью и поговорим про , которые помогут их избежать.

Почему сложно писать безопасный код на JS

Итак, вот 5 причин, почему сложно писать безопасный код на JS

Компилятор не поможет

JavaScript - интерпретируемый язык. А это значит, что компилятор не будет все время на что-нибудь жаловаться, отказываясь работать и подталкивая тебя поправить ошибки и оптимизировать код.

Динамическая суть JavaScript

JavaScript динамический, слаботипизированный и асинхронный. А это все признаки того, что попасть в беду легче легкого.

1. Языковые средства вроде eval и включения стороннего кода через script src позволяют исполнять строки прямо в рантайме. Как следствие - сложно дать «статические гарантии» того, что код будет вести себя определенным образом. Динамический анализ это тоже затрудняет (см. научную работу).

Использование eval

2. Слабая типизация приводит к тому, что применять устоявшиеся методы статического анализа непросто - по крайней мере в сравнении со статически типизированными языками (например, Java).

3. Асинхронные колбэки, вызовы которых JavaScript допускает через механизмы вроде setTimeout и XMLHttpRequest (тот самый знаменитый AJAX), по статистике прячут в себе больше всего коварных ошибок.

Замысловатые возможности JS

Чего только не притащили в JavaScript с годами! В частности, в нем есть прототипы , функции первого класса и замыкания . Они делают язык еще динамичнее, а написание безопасного кода - сложнее.

1. Прототипы. Смысл их в том, что программы пишутся в духе объектно ориентированного подхода, но без использования классов. При таком подходе объекты наследуют необходимые им свойства напрямую от других объектов (прототипов). При этом в JS прототипы могут быть переопределены прямо в рантайме. И если это переопределение случилось, то эффект сразу же распространяется на все объекты, которые наследуют свойства переопределяемого прототипа.

Как обрабатываются прототипы

Справедливости ради надо сказать, что в новых спецификациях ECMAScript классы тоже присутствуют.

2. Функции первого класса. У JS очень гибкая модель объектов и функций. Свойства объектов и их значения могут быть созданы, изменены или удалены прямо в рантайме, и ко всем есть доступ через функции первого класса.

3. Замыкания. Если объявить функцию внутри другой функции, то первая получает доступ к переменным и аргументам последней. Причем эти переменные продолжают существовать и остаются доступными внутренней функции - даже после того, как внешняя функция, в которой эти переменные определены, завершилась.

Из-за такой гибкости и динамичности JavaScript (см. пункты 1 и 3) определение набора всех доступных свойств объекта при статическом анализе - неразрешимая задача. Однако веб-разработчики повсеместно используют динамические особенности языка, а соответственно, пренебрегать ими при анализе кода нельзя. Иначе какая тут гарантия безопасности?

Тесное взаимодействие между JavaScript и DOM

Это нужно, чтобы обеспечить «бесшовное» обновление веб-страницы, прямо в рантайме. DOM, как известно, представляет собой стандартную объектную модель, нейтральную по отношению к платформам и языкам, которая предназначена для отрисовки документов HTML и XML. У DOM есть собственный API для работы с отображаемым документом: для динамического доступа, перемещения и обновления отображаемого документа (его содержимого, структуры и стиля). Изменения в DOM могут вноситься динамически, через JavaScript. И эти изменения сразу же отображаются в браузере.

Благодаря DOM загруженные в браузер веб-страницы можно обновлять поэтапно по ходу подгрузки данных с сервера. Однако у такого удобства есть и оборотная сторона: фрагменты кода, которые отвечают за динамическое взаимодействие между JS и DOM, особенно подвержены ошибкам.

Наиболее распространенные ошибки в веб-приложениях

Сложные событийные взаимодействия

JavaScript - это язык, управляемый событиями (event-driven). Он позволяет разработчикам регистрировать на узлах DOM так называемых «слушателей событий» - event listeners. И хотя большинство событий вызываются действиями пользователя, существуют и такие, которые могут быть инициированы и без этого, - например, события по времени и асинхронные вызовы. При этом каждое событие может отдаваться эхом по всему дереву DOM и активировать сразу несколько «слушателей». Иногда отследить все это - довольно нетривиальная задача.

Как обрабатываются события

По этим причинам код на JS может быть труден для понимания, анализа и тестирования. Облегчат жизнь веб-разработчику и помогут писать безопасный код специальные утилиты.

Утилиты для тестирования кода на JS

Существуют утилиты для парсинга (например, Esprima , Rhino), оптимизации (например, Google Closure Compiler) и статического анализа кода на наличие распространенных синтаксических ошибок (например, JSHint).

Кроме того, есть несколько проверенных фреймворков, которые помогают веб-разработчикам покрывать JS-код тестами. Среди них:

  • QUnit - популярный фреймворк для тестирования модулей;
  • Jasmine - BDD-фреймворк (Behavior-driven Development) для тестирования кода;
  • Mocha - фреймворк для тестирования кода, запускается как в Node.js, так и в браузере;
  • jsTestDriver - фреймворк, который в числе прочего может прогонять набор тестов сразу через несколько браузеров.

Кроме того, существуют тестирующие фреймворки, которые эмулируют поведение браузера и позволяют автоматически прогонять тестовые примеры. Они особенно актуальны при отладке участков кода, которые отвечают за взаимодействие между JS и DOM, и предоставляют удобную инфраструктуру для манипулирования DOM.

К примеру, Selenium , PhantomJS и SlimerJS предоставляют API, через который можно запускать экземпляры браузера и работать с ними. Через API ты можешь активировать события и получать доступ к элементам DOM прямо в рантайме - то есть тестировать код в условиях, максимально приближенных к реальным. Конечно, немалую часть работы придется проделывать вручную, но даже это уже неплохая помощь в тестировании.

Утилиты для статического анализа

Ранее утилиты для выявления проблемных участков кода представляли собой статические анализаторы. То есть, учитывая все динамические причуды JS, могли предоставить только ограниченную помощь. Однако и они бывают полезными в анализе. Вот несколько основных примеров.

WARI - статический анализатор, который исследует зависимости между функциями JS, стилями CSS, тегами HTML и изображениями. Смысл этой утилиты - находить при статическом анализе неиспользуемые ресурсы. Однако с динамикой WARI, конечно, не справится.

JSLint - утилита для анализа статического кода, которая сама написана на JavaScript. Она проверяет код на соответствие хорошим практикам.

Google Closure Compiler - JS-оптимизатор, который автоматически переписывает код с целью сделать его быстрее и компактнее. Заодно в трубу вылетают все комментарии и любые неиспользуемые участки кода.

WebScent (см. научную работу) - продвинутый статический анализатор. В работе он исходит из того, что клиентский JS-код (тот, который загружается в браузер) не хранится на стороне сервера в целом виде, а рассеян по серверному коду кусками. «Душок» в этих кусках не может быть легко обнаружен до тех пор, пока из них не будет сгенерирован цельный клиентский код. WebScent анализирует клиентский код с тем, чтобы найти проблемные места в серверном коде. При этом работа статического анализатора WebScent в основном сводится к распутыванию замесов HTML, CSS и JS - с целью обнаружить дублирующийся код и ошибки в синтаксисе HTML.

Утилиты для динамического анализа

JSNose - утилита, в которой объединены статический и динамический анализ. Она анализирует код на наличие тринадцати антипаттернов. Семь из них (в том числе lazy object и long function) - общие для всех языков программирования, а шесть остальных (closure smells, excessive global variables, nested callbacks и другие) специфичны для JavaScript.

DOMPletion - автоматизированная утилита, которая помогает веб-разработчику понимать код при просмотре: объясняет причину присутствия структур DOM, выполняет динамический анализ, а также предоставляет умный автокомплит для кода, который взаимодействует с DOM.

Clematis - фреймворк, который помогает распутывать сложные событийные взаимодействия. Clematis детально фиксирует все события, которые срабатывают при выполнении, и визуализирует их в виде абстрактной поведенческой модели, в которой отражаются временные и причинно-следственные связи между компонентами и событиями.

Выводы

Итак, отследить происходящее при выполнении скриптов на JS бывает непросто, но, вооружившись подходящими инструментами, найти и переписать проблемные места можно даже в самом запутанном коде. Впрочем, JavaScript не стоит на месте: в нем появляются новые и новые возможности, теперь он часто используется для написания приложений (как мобильных, так и десктопных), а также все чаще встречается на серверах (и не только) благодаря Node.js. А это значит, что и искусство ловли багов нужно выводить на новый уровень.

У каждого из команды ][ - свои предпочтения по части софта и утилит для пентеста. Посовещавшись, мы выяснили: выбор так разнится, что можно составить настоящий джентльменский набор из проверенных программ. На том и решили. Чтобы не делать сборную солянку, весь список разбит на темы. Сегодня мы разберем статические анализаторы кода для поиска уязвимостей в приложениях, когда на руках – их исходники.

Наличие исходных кодов программы существенно упрощает поиск уязвимостей. Вместо того чтобы вслепую манипулировать различными параметрами, которые передаются приложению, куда проще посмотреть в сорцах, каким образом она их обрабатывает. Скажем, если данные от пользователя передаются без проверок и преобразований, доходят до SQL-запроса – имеем уязвимость типа SQL injection. Если они добираются до вывода в HTML-код – получаем классический XSS. От статического сканера требуется четко обнаруживать такие ситуации, но, к сожалению, выполнить это не всегда так просто как кажется.

Современные компиляторы

Может показаться забавным, но одними из самых эффективных анализаторов кода являются сами компиляторы. Конечно, предназначены они совсем для другого, но в качестве бонуса каждый из них предлагает неплохой верификатор исходников, способный обнаружить большое количество ошибок. Почему же он не спасает? Изначально настройки такой верификации кода выставлены достаточно лояльно: в результате, чтобы не смущать программиста, компилятор начинает ругаться только в случае самых серьезных косяков. А вот и зря - если поставить уровень предупреждений повыше, вполне реально откопать немало сомнительных мест в коде. Выглядит это примерно следующим образом. Скажем, в коде есть отсутствие проверки на длину строки перед копированием ее в буфер. Сканер находит функцию, копирующую строку (или ее фрагмент) в буфер фиксированного размера без предварительной проверки ее длины. Он прослеживает траекторию передачи аргументов: от входных данных до уязвимой функции и смотрит: возможно ли подобрать такую длину строки, которая бы вызывала переполнение в уязвимой функции и не отсекалась бы предшествующими ей проверками. В случае если такой проверки нет, находим практически 100% переполнение буфера. Главная сложность в использовании для проверки компилятора - заставить его "проглотить" чужой код. Если ты хоть раз пытался скомпилировать приложение из исходников, то знаешь, насколько сложно удовлетворить все зависимости, особенно в больших проектах. Но результат стоит того! Тем более, помимо компилятора в мощные IDE встроены и некоторые другие средства для анализа кода . К примеру, на следующий участок кода в Visual Studio будет выдано предупреждение об использовании в цикле функции _alloca, что может быстро переполнить стек:

char *b;
do {
b = (char*)_alloca(9)
} while(1)

В этом заслуга статического анализатора PREfast. Подобно FxCop, предназначенной для анализа управляемого кода, PREfast изначально распространялся в виде отдельной утилиты и лишь позже стал частью Visual Studio.

RATS - Rough Auditing Tool for Security

Сайт: www.securesoftware.com
Лицензия: GNU GPL
Платформа: Unix, Windows
Языки: С++, PHP, Python, Ruby

Ошибка ошибке - рознь. Часть тех огрех, которые допускают программисты, некритична и грозит только нестабильностью программы. Другие, напротив, позволяют инжектировать шелл-код и выполнять произвольные команды на удаленном сервере. Особый риск в коде представляют команды, позволяющие выполнить buffer overflow и другие похожие типы атак. Таких команд очень много, в случае с C/C++ это функции для работы со строками (xstrcpy(), strcat(), gets(), sprintf(), printf(), snprintf(), syslog()), системные команды (access(), chown(), chgrp(), chmod(), tmpfile(), tmpnam(), tempnam(), mktemp()), а также команды системных вызовов (exec(), system(), popen()). Вручную исследовать весь код (особенно, если он состоит из нескольких тысяч строк) довольно утомительно. А значит, можно без труда проглядеть передачу какой-нибудь функции непроверенных параметров. Значительно облегчить задачу могут специальные средства для аудита, в том числе, известная утилита RATS (Rough Auditing Tool for Security ) от известной компании Fortify. Она не только успешно справится с обработкой кода, написанного на C/C++, но сможет обработать еще и скрипты на Perl, PHP и Python. В базе утилиты находится внушающая подборка с детальным описанием проблемных мест в коде. С помощью анализатора она обработает скормленный ей сорец и попытается выявить баги, после чего выдаст информацию о найденных недочетах. RATS работает через командную строку, как под Windows, так и *nix-системами.

Yasca

Сайт: www.yasca.org
Лицензия: Open Source
Платформа: Unix, Windows
Языки: С++, Java, .NET, ASP, Perl, PHP, Python и другие.

Yasca так же, как и RATS не нуждается в установке, при этом имеет не только консольный интерфейс, но и простенький GUI. Разработчики рекомендуют запускать утилиту через консоль - мол, так возможностей больше. Забавно, что движок Yasca написан на PHP 5.2.5, причем интерпретатор (в самом урезанном варианте) лежит в одной из подпапок архива с программой. Вся программа логически состоит из фронт-енда, набора сканирующих плагинов, генератора отчета и собственно движка, который заставляет все шестеренки вращаться вместе. Плагины свалены в директорию plugins - туда же нужно устанавливать и дополнительные аддоны. Важный момент! Трое из стандартных плагинов, которые входят в состав Yasca , имеют неприятные зависимости. JLint, который сканирует Java"овские.class-файлы, требует наличия jlint.exe в директории resource/utility. Второй плагин - antiC, используемый для анализа сорцов Java и C/C++, требует antic.exe в той же директории. А для работы PMD, который обрабатывает Java-код, необходима установленная в системе Java JRE 1.4 или выше. Проверить правильность установки можно, набрав команду "yasca ./resources/test/". Как выглядит сканирование? Обработав скормленные программе сорцы, Yasca выдает результат в виде специального отчета. Например, один из стандартных плагинов GREP позволяет с помощью паттернов, описанных в.grep файлах, указать уязвимые конструкции и легко выявлять целый ряд уязвимостей. Набор таких паттернов уже включен в программу: для поиска слабого шифрования, авторизации по "пароль равен логину", возможные SQL-инъекции и много чего еще. Когда же в отчете захочется увидеть более детальную информации, не поленись установить дополнительные плагины. Чего стоит одно то, что с их помощью можно дополнительно просканировать код на на.NET (VB.NET, C#, ASP.NET), PHP, ColdFusion, COBOL, HTML, JavaScript, CSS, Visual Basic, ASP, Python, Perl.

Cppcheck

Сайт:
Лицензия: Open Source
Платформа: Unix, Windows
Языки: С++

Разработчики Cppcheck решили не разбрасываться по мелочам, а потому отлавливают только строго определенные категории багов и только в коде на С++. Не жди, что программа продублирует предупреждения компилятора - он обойдется без суфлера. Поэтому не поленись поставить для компилятора максимальный уровень предупреждений, а с помощью Cppcheck проверь наличие утечек памяти, нарушений операций allocation-deallocation, различных переполнений буфера, использования устаревших функций и многого другого. Важная деталь: разработчики Cppcheck постарались свести количество ложных срабатываний к минимуму. Поэтому, если прога фиксирует ошибку, можно с большой вероятностью сказать: "Она действительно есть!" Запустить анализ можно как из-под консоли, так и с помощью приятного GUI-интерфейса, написанного на Qt и работающего под любой платформой.

graudit

Сайт: www.justanotherhacker.com/projects/graudit.html
Лицензия: Open Source
Платформа: Unix, Windows
Языки: C++, PHP, Python, Perl

Этот простой скрипт, совмещенный с набором сигнатур, позволяет найти ряд критических уязвимостей в коде, причем поиск осуществляется с помощью всем известной утилиты grep. О GUI-интерфейсе тут неуместно даже упоминать: все осуществляется через консоль. Для запуска есть несколько ключей, но в самом простом случае достаточно указать в качестве параметра путь к исходникам:

graudit /path/to/scan

Наградой за старание будет цветастый отчет о потенциально эксплуатируемых местах в коде. Надо сказать, что, помимо самого скрипта (а это всего 100 строчек кода на Bash), ценность представляют сигнатурные базы, в которых собраны регекспы и названия потенциально уязвимых функций в разных языках. По умолчанию включены базы для Python, Perl, PHP, C++ - можно взять файлы из папки signatures и использовать в своих собственных разработках.

SWAAT

Сайт: www.owasp.org
Лицензия: Open Source
Платформа: Unix, Windows
Языки: Java, JSP, ASP .Net, PHP

Если в graudit для задания сигнатуры уязвимости используются текстовые файлы, то в SWAAT – более прогрессивный подход с помощью XML-файлов. Вот так выглядит типичная сигнатура:

vuln match - регулярное выражение для поиска;
type - указывает на тип уязвимости:
severity - обозначает уровень риска (high, medium или low)
alt - альтернативный вариант кода для решения проблемы

SWAAT считывает базу сигнатур и с ее помощью пытается найти проблемные участки кода в исходниках на Java, JSP, ASP .Net, и PHP. База постоянно пополняется и помимо списка "опасных" функций, сюда включены типичные ошибки в использовании форматирования строк и составлении SQL-запросов. Примечательно, что прога написана на C#, однако отлично работает и под никсами, благодаря проекту Mono - открытой реализации платформы.Net.

PHP Bug Scanner

Сайт: raz0r.name/releases/php-bug-scanner
Лицензия: Freeware
Платформа: Windows
Языки: PHP

Если тебе нужно провести статический анализ PHP-приложения, рекомендую попробовать PHP Bug Scanner , которую написал наш автор - raz0r. Работа проги основана на сканировании различных функций и переменных в PHP-скриптах, которые могут быть задействованы при проведении веб-атак. Описание таких ситуаций оформляется в виде так называемых пресетов, причем в программу уже включены 7 специальных прессетов, сгруппированных по категориям:

  • code execution;
  • command execution;
  • directory traversal;
  • globals overwrite;
  • include;
  • SQL-injection;
  • miscellaneous.

Забавно, что прога написана на PHP/WinBinder и скомпилирована bamcompile , поэтому выглядит так же, как и обычное Windows-приложение. Через удобный интерфейс пентестер может включить или отключь анализ кода на наличие тех или иных уязвимостей.

Pixy

Сайт: pixybox.seclab.tuwien.ac.at
Лицензия: Freeware
Платформа: Unix, Windows
Языки: PHP

В основе работы инструмента - сканирование исходного кода и построение графов потоков данных. По такому графу прослеживается путь данных, которые поступают извне программы - от пользователя, из базы данных, от какого-нибудь внешнего плагина и т.п. Таким образом строится список уязвимых точек (или входов) в приложениях. С помощью паттернов, описывающих уязвимость, Pixy проверяет такие точки и позволяет определить XSS- и SQL-уязвимости. Причем сами графы, которые строятся во время анализа, можно посмотреть в папке graphs (например, xss_file.php_1_dep.dot) - это очень полезно для того чтобы понять, почему именно тот или иной участок кода считается Pixy-уязвимым. Вообще, сама разработка крайне познавательна и демонстрирует, как работают продвинутые утилиты для статического анализа кода. На страничке документации разработчик доходчиво рассказывает о разных этапах работы программы, объясняет логику и алгоритм того, как должен анализироваться прогой тот или иной фрагмент кода. Сама программа написана на Java и распространяется в открытых исходниках, а на домашней страничке есть даже простенький онлайн-сервис для проверки кода на XSS-уязвимости.

Ounce 6

Сайт: www.ouncelabs.com/products
Лицензия: Shareware
Платформа: Windows

Увы, существующие бесплатные решения пока на голову ниже, чем коммерческие аналоги. Достаточно изучить качество и детальность отчета, который составляет Ounce 6 – и понять, почему. В основе программы лежит специальный анализирующий движок Ounce Core, который проверяет код на соответствие правилам и политикам, составленными командой профессиональных пентестеров, аккумулировавших опыт известных security-компаний, хакерского комьюнити, а также стандартов безопасности. Программа определяет самые разные уязвимости в коде: от переполнения буфера до SQL-инъекций. При желании Ounce несложно интегрируется с популярными IDE, чтобы реализовать автоматическую проверку кода во время сборки каждого нового билда разрабатываемого приложения. Кстати говоря, компанию-разработчика - Ounce Labs - летом этого года приобрела сама IBM. Так что продукт, скорее всего, продолжит развитие уже как часть одного из коммерческих приложений IBM.

Klocwork Insight

Сайт: www.klocwork.com
Лицензия: Shareware
Платформа: Windows
Языки: C++, Java, C#

Долгое время этот, опять же, коммерческий продукт реализовал статическое сканирование кода только для C, C+ и Java. Но, как только вышли Visual Studio 2008 и.NET Framework 3.5, разработчики заявили о поддержке C#. Я прогнал программу на двух своих вспомогательных проектах, которые на скорую руку написал на "шарпе" и программа выявила 7 критических уязвимостей. Хорошо, что они написаны исключительно для внутреннего использования:). Klocwork Insight изначально настроен, прежде всего, на работу в связке с интегрированными средами разработки. Интеграция с теми же Visual Studio или Eclipse выполнена чрезвычайно удачно – начинаешь всерьез задумываться, что такая функциональность должна быть реализована в них по умолчанию:). Если не брать в расчет проблемы с логикой работы приложения и проблемы с быстродействием, то Klocwork Insight отлично справляется с поиском переполнения буфера, отсутствия фильтрации пользовательского кода, возможности SQL/Path/Cross-site инъекций, слабого шифрования и т.п. Еще одна интересная опция – построение дерева выполнения приложения, позволяющего быстро вникнуть в общий принцип работы приложения и отдельно проследить, например, за обработкой какого-либо пользовательского ввода. А для быстрого конструирования правил для проверки кода предлагается даже специальный инструмент - Klocwork Checker Studio .

Coverity Prevent Static Analysis

Сайт: www.coverity.com/products
Лицензия: Shareware
Платформа: Windows
Языки: C++, Java, C#

Один из самых известных статических анализаторов кода на C/C++, Java и C#. Если верить его создателям, – решение используется более чем 100.000 разработчиков по всему миру. Продуманные механизмы позволяют автоматизировать поиск утечек памяти, неотловленных исключений, проблем с быстродействием и, конечно же, уязвимостей в безопасности. Продукт поддерживает разные платформы, компиляторы (gcc, Microsoft Visual C++ и многие другие), а также интегрируется с различными средами разработки, прежде всего Eclipse и Visual Studio. В основе обхода кода используются не тупые алгоритмы обхода от начала до конца, а что-то вроде отладчика, анализирующего, как программа поведет в себя в различных ситуациях после встречи ветвления. Таким образом достигается 100% покрытия кода. Столь сложный подход потребовался в том числе, чтобы всецело анализировать многопоточные приложения, специально оптимизированные для работы на многоядерных процессорах. Coverity Integrity Center позволяет находить такие ошибки как состояние гонки (ошибка проектирования многозадачной системы, при которой работа системы зависит от того, в каком порядке выполняются части кода), тупики и многое другое. Зачем это нужно реверсерам? Спроси об этом разработчиков 0day сплоитов для Firefox и IE:).

OWASP Code Crawler

Сайт: www.owasp.org
Лицензия: GNU GPL
Платформа: Windows
Языки: Java, C#, VB

Создатель этой тулзы Алессио Марциали - автор двух книжек по ASP.NET, авторитетный кодер высоконагруженных приложений для финансового сектора, а также пентестер. В 2007 году он опубликовал информацию о критических уязвимостях в 27 правительственных сайтах Италии. Его детище – OWASP Code Crawler – предназначенное для статического анализа кода.NET и J2EE/JAVA, открыто доступно в инете, а в конце года автор обещается выпустить новую версию программы с намного большей функциональностью. Но самое-то главное реализовано уже сейчас – анализ исходников на C#, Visual Basic и Java. Файлы для проверки выбираются через GUI-интерфейс, а сканирование запускается автоматически. Для каждого проблемного участка кода выводится описание уязвимости в разделе Threat Description. Правда, поле OWASP Guidelines , вероятно, указывающее пути решения проблемы, увы, пока не доступно. Зато можно воспользоваться экспериментальной особенностью сканирования кода на удаленной машине, доступной во вкладке Remote Scan. Автор обещает серьезно прокачать эту возможность и, в том числе, агрегировать исходники приложения для анализа прямо из системы контроля версий.

WARNING

Информация представлена в целях ознакомления и, прежде всего, показывает, каким образом разработчики могут избежать критических ошибок во время разработки приложений. За использование полученных знаний в незаконных целях ни автор, ни редакция ответственности не несут.

Представляет собой модульный упаковщик, который создаёт граф зависимостей со всеми модулями для приложения на JavaScript. Webpack упаковывает модули в один или несколько маленьких пакетов для загрузки браузером. Кроме того, Webpack может использоваться в качестве средства запуска задач, так как он анализирует зависимости между модулями и образовывает ресурсы (ассеты). Подробнее с использованием Webpack в своих проектах вы можете ознакомиться в нашей .

  • Grunt - таск раннер, предназначенный для автоматизации повторяющихся и трудоёмких задач, которые отнимают много времени. В его программной экосистеме существует огромное количество плагинов (более 6000).
  • Gulp - не очередной диспетчер запуска задач, а инструмент с интересным подходом: он определяет задачи в JavaScript как функции, также GUl автоматизирует «болезненные» задачи, предлагая обширную программную экосистему (более 2700 плагинов), также он обеспечивает лучшую прозрачность и контроль над процессом.
  • Browserify позволяет разработчикам программного обеспечения использовать модули стиля NodeJS в браузерах. Вы определяете зависимости, а Broweserify упаковывает всё это в аккуратный JS-файл.
  • Brunch.io - инструмент, основными идеями которого являются скорость и простота. Он поставляется с простой конфигурацией и подробной документацией для быстрого запуска. Brunch автоматически создаёт карту JS-файлов вместе с таблицами стилей CSS, что упрощает процесс отладки на стороне клиента.
  • Yeoman - универсальный инструмент, который может использоваться с почти любым языком программирования (JavaScript, Python, C#, Java и прочие). Эта базовая система кодогенерации с богатой программной экосистемой (более 6200 плагинов) служит для разработки веб-приложений. Благодаря Yeoman вы можете быстро создавать новые проекты, не забывая об обслуживании и улучшении уже существующих.
  • IDE и редакторы кода

    • Swagger - это набор правил и инструментов для описания API. Инструмент представляет собой языконезависимую утилиту. Это значит, что Swagger создаёт чёткую документацию, которая читается одинаково хорошо как человеком, так и машиной, позволяя автоматизировать процессы зависящие от API.
    • JSDoc - набор инструментов, автоматически создающий многостраничную текстовую документацию (HTML, JSON, XML и т. д.) из комментариев из исходного кода на JavaScript. Это приложение может пригодиться для управления крупномасштабными проектами.
    • jGrouseDoc (jGD) - это гибкий инструмент с открытым исходным кодом, который позволяет разработчикам генерировать API из комментариев из исходного кода на JavaScript. jGD документирует не только переменные и функции, но и пространства имён, интерфейсы, пакеты и некоторые другие элементы.
    • YUIDoc - приложение, написанное на NodeJS. Оно использует синтаксис, подобный тому, который применяется в Javadoc и Doxygen. Также инструмент может похвастаться поддержкой предварительного просмотра в реальном времени, расширенной поддержкой языка и продвинутой разметку.
    • Docco - бесплатный инструмент для документации, написанный на «литературном» CoffeeScript. Он создаёт HTML-документ для отображения ваших комментариев, чередующихся с кодом. Следует отметить, что инструмент поддерживает не только JavaScript, но и другие языки. Например, Python, Ruby, Clojure и прочие.

    Инструменты тестирования

    Инструменты тестирования для JavaScript созданы для обнаружения ошибок на этапе разработки, чтобы избежать в будущем ошибок у пользователей. С ростом сложности пользовательских приложений автоматические тесты не только повышают производительность приложения, но и помогают компаниям сохранить бюджет.

    • Jasmine - BDD-фреймворк (Behavior-driven Development - разработка на основе поведений) служит для тестирования JS-кода. У него нет внешних зависимостей, и он не требует запуска DOM. Jasmine имеет чистый и понятный синтаксис, что позволяет ускорять и упрощать тестирование. Также фреймворк может использоваться для тестирования кода Python и Ruby.
    • Mocha - это функциональная тестовая среда, работающая на Node.js в браузере. Она проводит тесты последовательно для обеспечения гибкой и точной отчётности, делая асинхронные тесты весёлыми и лёгкими. Mocha часто используется вместе с Chai для проверки результатов теста.
    • PhantomJS часто используется для интерфейсных тестов и юнит-тестов. Учитывая то, что это что-то вроде «безголового» WebKit, скрипты выполняются намного быстрее. Также он включает в себя встроенную поддержку различных веб-стандартов. Например, JSON, Canvas, обработку DOM, SVG и селекторы CSS.
    • Protractor - это сквозной тестовый фреймворк, написанный на Node.js для тестирования приложений на AngularJS и Angular. Он был создан на основе WebDriverJS и проверяет приложения подобно конечному пользователю, используя специальные драйвера и встроенные события.

    Инструменты отладки

    Отладка кода - довольно трудоёмкий и поглощающий время процесс для JavaScript-разработчиков. Инструменты для отладки кода будут особенно полезны при работе с тысячами строк кода. Многие из инструментов отладки обеспечивают довольно точные результаты.

    • JavaScript Debugger - инструмент от сообщества разработчиков Mozilla (MDN), который может быть использован как автономное веб-приложение для отладки кода в разных браузерах. Firefox предлагает локальные и удалённые функциональные возможности, а также возможность отладки кода на Android-устройстве с помощью Firefox для Android.
    • Chrome Dev Tools - набор инструментов, включающий в себя несколько утилит для отладки кода JavaScript, редактирования CSS и тестирования производительности приложений.
    • ng-inspector - кроссбраузерное расширение, которое призвано помочь разработчикам с написанием, пониманием и отладкой приложений на AngularJS. Утилита поставляется с обновлениями в реальном времени, подсветкой DOM, прямым доступом к областям, моделям и прочим элементам приложения.
    • Augury - расширение для браузера Google Chrome и отладки приложений на Angular 2. Оно позволяет разработчикам приложений на Angular 2 напрямую анализировать структуру приложения и рабочие характеристики, а также позволяет обнаружить изменения.

    Инструменты безопасности

    • Snyk - коммерческий инструмент для обнаружения, исправления и предотвращения известных уязвимостей в приложениях на JavaScript, Java и Ruby. Служба имеет собственную базу данных уязвимостей и берёт данные из NSP и NIST NVD. Патчи и обновления, которые предлагает компания, позволяют разработчикам предупредить риски, связанные с безопасностью.
    • Node Security Project предлагает полезные инструменты для сканирования зависимостей и обнаружения уязвимостей. NSP использует свою собственную базу данных, построенную на сканировании модулей npm, а также данные из общих баз данных, таких как NIST NVD (National Vulnerability Database). Кроме того, NSP обеспечивает интеграцию с программным обеспечением GitHub Pull Request и CI. Также имеется проверка в реальном времени, предупреждения и рекомендации по устранению уязвимостей в приложениях на Node.js.
    • RetireJS - это средство проверки зависимостей с открытым исходным кодом. Включает в себя различные компоненты, такие как сканер командной строки, плагин Grunt, расширения Firefox и Chrome, плагины Burp и OWASP ZAP. Retirejs собирает информацию об уязвимостях из NIST NVD и других источников, таких как системы отслеживания ошибок, блоги и списки рассылки.
    • Gemnasium - это коммерческий инструмент с бесплатной пробной версией. Он поддерживает различные технологии и пакеты, включая Ruby, PHP, Bower (JavaScript), Python и npm (JavaScript). Инструмент безопасности Gemnasium поставляется с полезными функциями, такими как автоматическое обновление, оповещения в реальном времени, уведомления о безопасности и интеграция с сервисом Slack.
    • OSSIndex поддерживает различные экосистемы (Java, JavaScript и.NET / C #) и множество платформ, таких как NuGet, npm, Bower, Chocolatey, Maven, Composer, Drupal и MSI. Он собирает информацию об уязвимостях из Национальной базы данных уязвимостей (NVD) и отзывов. Также он обрабатывает информацию от членов сообщества.

    Инструменты аналитики и оптимизации кода

    Для проверки качества кода обычно обращаются к функциональному тестированию и юнит-тестированию. Однако существует еще один подход, который позволяет разработчикам проверять качество кода и его соответствие стандартам кодирования, а именно статический анализ кода.

    В настоящее время в современном программном обеспечении объединяются инструменты анализа статического кода во время разработки, чтобы исключить попадание некачественного кода в продакшен.

    • JSLint - это аналитический веб-инструмент для проверки качества кода JavaScript. Как только он обнаруживает проблему в источнике, он возвращает сообщение с описанием проблемы и приблизительным местоположением в коде. JSLint способен анализировать некоторые нормы стиля и раскрывать синтаксические ошибки и структурные проблемы.
    • JSHint - гибкий инструмент, развивающийся сообществом, для обнаружения ошибок и потенциальных проблем в вашем JS-коде, кроме того, JSHint - форк от JSLint. Основная цель этого инструмента статического анализа кода - помощь разработчикам JavaScript, работающим над сложными программами. Он способен обнаруживать ошибки синтаксиса, неявное преобразование типов данных или отсутствие переменной. Однако он не может определить скорость и правильность работы вашего приложения, как и не сможет определить проблемы с памятью в вашем приложении. JSHint - форк от JSLint.
    • ESLint – это линтер с открытым исходным кодом для веб-приложений JSX и JavaScript. Он помогает обнаруживать сомнительные шаблоны или находить код, который не соответствует конкретным стилям. Это позволяет разработчикам обнаруживать ошибки в JS-коде без его выполнения, тем самым экономя время. Будучи написанным на Node.js, инструмент предлагает оперативную среду выполнения и плавную установку через npm.
    • Flow - статический контролёр кода для JavaScript, разработанный компанией Facebook. Он использует аннотации статического типа для проверки кода на предмет ошибок. Типы - параметры, установленные разработчиками, а Flow проверяет ваше программное обеспечение на соответствие требованиям.

    Инструменты управления версиями

    • В последние годы Git стала широко используемой системой контроля версий как для небольших, так и для крупных проектов. Эта бесплатная утилита обеспечивает отличную скорость работы и эффективность. Её популярность объясняется распределённой системой и различными типами элементов управления, а также промежуточной областью, где версии могут быть просмотрены и отформатированы непосредственно перед завершением фиксации.
    • Инструмент Subversion или SVN приобрёл огромную популярность, и он по-прежнему широко используется в проектах с открытым исходным кодом и такими платформами, как Python Apache или Ruby. Этот CVS поставляется со множеством функций, позволяющих управлять различными операциями (переименование, копирование, удаление и т. д.), слияниями, блокировкой файлов и многим другим.

    Инструменты управления пакетами и зависимостями

    Список лучших инструментов для разработки на JavaScript может продолжаться до бесконечности. В этой статье вы увидели лишь популярные и надёжные инструменты, которые служат основой для качественных продуктов.

    Далеко не каждая строка моего кода получается идеальной с первого же раза. Ну, в некоторых случаях… Иногда… Ладно – практически никогда. Правда заключается в том, что я трачу значительно больше времени на исправление своих собственных глупых ошибок, чем мне хотелось бы. Именно поэтому я использую статические анализаторы практически в каждом написанном мной файле JavaScript.

    Статические анализаторы просматривают код и находят в нем ошибки, прежде чем вы его запустите. Они выполняют простые проверки, например, проверку синтаксиса принудительного исполнения (например, наличия табуляции вместо пробелов) и более глобальные проверки, такие как проверка того, чтобы функции не были слишком сложными. Статические анализаторы также ищут ошибки, которые невозможно найти в процессе тестирования, например, == вместо ===.

    В больших проектах и при работе в больших командах вам не помешает небольшая помощь в поиске таких «простых» багов, которые на самом деле оказываются не такими простыми, как кажутся.

    JSLint, JSHint и Closure Compiler

    Есть три основных варианта статических анализаторов для JavaScript: JSLint, JSHint и Closure Compiler.

    JSLint был первым статическим анализатором для JavaScript. Его можно запустить на официальном сайте или использовать одну из надстроек, которые можно запускать в локальных файлах. JSLint находит много важных ошибок, но он очень жесткий. Вот яркий пример:

    Var s = "mystring"; for (var i = 0; i < s.length; i++) { console.log(s.charAt(i)); }

    JSLint показывает в этом коде две ошибки:

    Unexpected "++". Move "var" declarations to the top of the function.

    Первая проблема – это определение переменной i в условиях цикла. JSLint также не принимает оператор ++ в конце определения цикла. Он хочет, чтобы код выглядел следующим образом:

    Var s = "mystring"; var i; for (i = 0; i < s.length; i = i + 1) { console.log(s.charAt(i)); }

    Я ценю создателей JSLint, но как по мне – это перебор. Он оказался жестким и для Антона Ковалева, поэтому он создал JSHint.

    JSHint работает так же, как и JSLint, но он написан в дополнение к Node.js, а потому он более гибкий. JSHint включает большое количество опций, что позволяет выполнять пользовательские проверки путем написания своего собственного генератора отчетов.
    Запустить JSHint можно с сайта , но в большинстве случаев лучше установить JSHint в качестве локального инструмента командной строки с помощью Node.js. Как только вы установите JSHint, его можно запустить в ваших файлах с помощью такой команды:

    Jshint test.js

    JSHint также включает плагины для популярных текстовых редакторов, поэтому его можно запускать в процессе написания кода.

    CLOSURE COMPILER

    Closure Compiler от Google – это совсем другая разновидность программы. Как предполагает его название, он представляет собой не только программу для проверки, но и компилятор. Он написан на Java и основан на анализаторе Rhino от Mozilla. Closure Compiler включает простой режим для выполнения базовой проверки кода, и более сложные режимы, позволяющие выполнять дополнительную проверку и обеспечивать соблюдение определений отдельных видов.

    Closure Compiler сообщает об ошибках в коде JavaScript, но также создает минимизированные версии JavaScript. Компилятор удаляет пустое пространство, комментарии и неиспользуемые переменные и упрощает длинные выражения, делая скрипт максимально компактным.

    Google сделал очень простую версию компилятора, доступную в сети , но скорее всего, вы захотите скачать Closure Compiler и запустить его локально.

    Closure Compiler после проверки кода выводит список файлов в один минимизированный файл. Таким образом, вы можете запустить его, скачав файл compiler.jar.

    Java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js

    Выбираем правильную программу проверки

    В своих проектах я комбинирую Closure Compiler и JSHint. Closure Compiler выполняет минимизацию и базовую проверку, в то время как JSHint проводит более сложный анализ кода. Эти две программы отлично работают вместе, и каждая из них охватывает те области, которые не может охватить другая. Кроме того, я могу использовать возможности расширения JSHint, чтобы писать пользовательские программы проверки. Одна написанная мной общая программа проверяет определенные функции, которые мне не нужны, например вызов функций, которых не должно быть в моем проекте.

    Теперь, когда мы рассмотрели несколько программ для проверки, давайте разберем немного плохого кода. Каждый из этих шести примеров представляет собой код, который не стоит писать, и ситуации, в которых программы проверки кода могут спасти вас.

    В этой статье для большинства примеров используется JSHint, но Closure Compiler обычно выдает похожие предупреждения.

    == или ===?

    JavaScript – это язык с динамической типизацией. Вам не нужно определять типы в процессе написания кода, при этом они существуют при запуске.

    JavaScript предлагает два оператора сравнения для управления такими динамическими типами: == и ===. Давайте рассмотрим это на примере.

    Var n = 123; var s = "123"; if (n == s) { alert("Переменные равны"); } if (n === s) { alert("Переменные идентичны"); }

    Оператор сравнения == - это остатки языка С, в который JavaScript уходит корнями. Его использование практически всегда является ошибкой: сравнивание значений отдельно от типов редко является тем, что разработчик на самом деле хочет сделать. На самом деле, число «сто двадцать три» отличается от строки «один два три». Эти операторы легко неправильно написать и еще легче неправильно прочесть. Проверьте этот код с помощью JSHint и вы получите следующее:

    Test.js: line 9, col 12, Expected "===" and instead saw "==".

    Неопределенные переменные и поздние определения

    Давайте начнем с простого кода:

    Function test() { var myVar = "Hello, World"; console.log(myvar); }

    Видите баг? Я совершаю эту ошибку каждый раз. Запустите этот код, и вы получите ошибку:

    ReferenceError: myvar is not defined

    Давайте сделаем проблему немного более сложной:

    Function test() { myVar = "Hello, World"; console.log(myVar); }

    Запустите этот код, и вы получите следующее:

    Hello, World

    Этот второй пример работает, но у него есть очень неожиданные побочные действия. Правила для определения переменных JavaScript и области видимости оказываются, в лучшем случае, запутанными. В первом случае JSHint сообщит следующее:

    Test.js: line 3, col 17, "myvar" is not defined.

    Во втором случае он сообщит такое:

    Test.js: line 2, col 5, "myVar" is not defined. test.js: line 3, col 17, "myVar" is not defined.

    Первый пример поможет вам избежать ошибки времени выполнения программы. Вам не нужно тестировать свое приложение - JSHint найдет ошибку за вас. Второй пример хуже, так как в результате тестирования вы не найдете баг.

    Проблема второго примера коварно незаметная и сложная. Переменная myVar теперь исчезла из своей области видимости и поднялась в глобальную область. Это означает, что она будет существовать и иметь значение Hello, World даже после запуска функции test. Это называется «загрязнение глобальной области видимости».

    Переменная myVar будет существовать для каждой другой функции, которая будет запущена после функции test. Запустите следующий код после того, как выполните функцию test:

    Console.log("myVar: " + myVar);

    Вы все равно получите Hello, World. Переменная myVar будет висеть по всему вашему коду как шаблон, который приводит к сложным багам, которые вы будете искать всю ночь перед релизом, а все потому, что вы забыли вписать var.

    И преподаватель Нетологии, написал для блога цикл статей о EcmaScript6. В первой части на примерах рассмотрим динамический анализ кода в EcmaScript с помощью Iroh.js.

    Статический и динамический анализ кода

    Средства анализа кода — полезный инструмент, позволяющий обнаруживать и выявлять ошибки и особенности в работе кода. Анализ кода бывает статическим и динамическим. В первом случае производится разбор и анализ исходного кода без его выполнения, во втором — выполнение происходит в управляемой среде-песочнице (sandboxing), предоставляющей метаинформацию об элементах приложения в процессе его выполнения.

    Выводы

    Iroh.js — мощный и функциональный инструмент для динамического анализа кода в EcmaScript-е. Этот инструмент может быть использован как для анализа кода, включая построения графа вызовов, вывода актуальных типов и значений в переменных и объектах, так и для модификации кода на лету, включая исправления кода, основанные на событиях.

    Динамический анализ — довольно сложный метод, однако для EcmaScript, учитывая утиную типизацию, наличие host-объектов и нативных функций, позволяющих менять поведения кода на лету, это единственный способ для анализа и отладки кода в процессе выполнения. Iroh.js также может использовать для создания функциональных тестов код без необходимости его предварительной модификации для экспорта значений.



    Рекомендуем почитать

    Наверх