Enable no-unsanitized recommended rules and verify TypeScript DOM sink diagnostics.
71 lines
7.2 KiB
Markdown
71 lines
7.2 KiB
Markdown
# Security-плагины ESLint
|
||
|
||
Проверено 28 сентября 2026 года для frontend: ESLint 10.11.0,
|
||
TypeScript и React 19. Рекомендация — добавить только
|
||
`eslint-plugin-no-unsanitized@4.1.5` с полным `configs.recommended`.
|
||
Решение реализовано: пакет добавлен в devDependencies, полный recommended
|
||
подключён в ESLint. Ниже сохранены результаты исследования до установки.
|
||
|
||
## Все пакеты из раздела Security
|
||
|
||
Источник списка: [awesome-eslint / Security](https://github.com/dustinspecker/awesome-eslint#security).
|
||
Версии и даты ниже — опубликованные `latest` из npm на момент проверки.
|
||
Широкий peer range сам по себе не доказывает работоспособность.
|
||
|
||
| Пакет | Версия; публикация | Заявленный peer ESLint | Решение для frontend |
|
||
| --- | --- | --- | --- |
|
||
| [no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized) | [4.1.5](https://registry.npmjs.org/eslint-plugin-no-unsanitized/4.1.5); 2026-02-19 | `^9 \|\| ^10` | Добавить: проверяет опасные присваивания и вызовы native DOM HTML API. Flat recommended включает `property` и `method` как errors. |
|
||
| [no-secrets](https://github.com/nickdeis/eslint-plugin-no-secrets) | [2.3.3](https://registry.npmjs.org/eslint-plugin-no-secrets/2.3.3); 2026-03-01 | `>=5` | Не добавлять: поиск секретов по entropy/patterns существенно пересекается с существующими Gitleaks и SonarJS. Flat config поддерживается; отсутствие рекомендации связано с дублированием. |
|
||
| [pii](https://github.com/shiva-hack/eslint-plugin-pii) | [1.0.2](https://registry.npmjs.org/eslint-plugin-pii/1.0.2); 2021-04-13 | `>=4.19.1` | Не добавлять: правило падает на ESLint 10. Проверяет email/даты рождения/IP/телефоны в литералах и комментариях, а не потоки персональных данных; потребует исключений для тестовых данных. |
|
||
| [pg](https://github.com/interlace-collie/eslint/tree/main/packages/eslint-plugin-pg) | [1.4.14](https://registry.npmjs.org/eslint-plugin-pg/1.4.14); 2026-08-06 | `^8.0.0 \|\| ^9.0.0 \|\| ^10.0.0` | Не добавлять: предназначен для Node.js с `pg`, которого во frontend нет. Пакет deprecated и переименован в `eslint-plugin-postgresql-security`; старое имя больше не обновляется. |
|
||
| [security](https://github.com/eslint-community/eslint-plugin-security) | [4.1.0](https://registry.npmjs.org/eslint-plugin-security/4.1.0); 2026-09-27 | Не указан | Уже установлен с recommended. Ориентирован главным образом на Node.js; не заменяет проверки DOM. |
|
||
| [xss](https://github.com/Rantanen/eslint-plugin-xss) | [0.1.12](https://registry.npmjs.org/eslint-plugin-xss/0.1.12); 2022-06-27 | Не указан | Не добавлять: правило падает на ESLint 10. Проверяет HTML-конкатенации/соглашения об именах и присваивания `location.href`; это не специализированная проверка React/TSX. |
|
||
|
||
## Что добавляет no-unsanitized
|
||
|
||
[Правило property](https://github.com/mozilla/eslint-plugin-no-unsanitized/blob/master/docs/rules/property.md)
|
||
проверяет присваивания `innerHTML`/`outerHTML`;
|
||
[method](https://github.com/mozilla/eslint-plugin-no-unsanitized/blob/master/docs/rules/method.md)
|
||
проверяет, в частности, `insertAdjacentHTML`, `document.write` и `document.writeln`.
|
||
В [исходнике method](https://github.com/mozilla/eslint-plugin-no-unsanitized/blob/master/lib/rules/method.js)
|
||
также есть проверки `createContextualFragment`, `setHTMLUnsafe` и dynamic import.
|
||
Следовательно, перед включением нужно прогнать весь lint, а не только HTML-примеры.
|
||
|
||
До подключения no-unsanitized [eslint.config.mjs](eslint.config.mjs) уже включал
|
||
React-проверку `dom-no-dangerously-set-innerhtml` и security-правила SonarJS.
|
||
Предварительная проверка через локальный `ESLint.lintText` показала пробел:
|
||
функция с `element.innerHTML = html` не получала security-диагностику,
|
||
тогда как JSX `dangerouslySetInnerHTML` получал
|
||
диагностику React. Это различие в покрытии, не обнаруженная уязвимость приложения:
|
||
таких production DOM-присваиваний при поиске не найдено.
|
||
|
||
Плагин понимает TS-синтаксис через TypeScript parser, включая `as`-выражения,
|
||
но не использует TypeScript type checker. Он не доказывает безопасность всех
|
||
потоков данных. У версии 4.1.5 нет runtime dependencies; Prettier указан только
|
||
в devDependencies самого плагина и при его обычной установке потребителем
|
||
не устанавливается.
|
||
|
||
## Проверка совместимости без установки
|
||
|
||
Опубликованные npm tarballs прочитаны в `/tmp`; использованы локальные
|
||
ESLint 10.11.0 и `@typescript-eslint/parser`, без lifecycle-скриптов пакетов.
|
||
Через `Linter.verify` с recommended no-unsanitized проверены:
|
||
|
||
- `innerHTML`/`outerHTML` с параметром `html: string` — обе ошибки найдены;
|
||
- `insertAdjacentHTML`/`document.write`/`document.writeln` — все три ошибки найдены;
|
||
- `innerHTML = html as string` — ошибка найдена;
|
||
- безопасный `textContent` и обычная TSX-интерполяция — без ошибок.
|
||
|
||
Отдельный запуск реальных правил `pii/no-email` и
|
||
`xss/no-location-href-assign` завершился
|
||
`TypeError: context.getSourceCode is not a function` на ESLint 10.
|
||
Это подтверждает несовместимость проверенных версий, несмотря на широкий
|
||
или отсутствующий peer range. Обходы через legacy adapters не предлагаются.
|
||
|
||
Поиск секретов уже выполняют [security workflow](.gitea/workflows/security.yml)
|
||
и pre-commit Gitleaks; SonarJS дополнительно проверяет hardcoded secrets.
|
||
Добавление ещё одного secret-scanner в ESLint сейчас не оправдано.
|
||
|
||
Активацию обоих правил и примеры опасных DOM-вставок проверяет
|
||
`npm run test:lint`; интеграцию зависимости — полный `npm run verify`.
|