Reactアプリを実装するとき、LinterとしてESLintを使っています。
また、Vite.jsを使ってReactアプリを実装する場合、デフォルトで導入される
や eslint-plugin-react などを使ってたりします。
そんな中、他にもReactのセキュリティ面を見てくれるESLintプラグインがないか調べたところ、Reactのセキュリティ関係のものについては
- https://www.npmjs.com/package/eslint-plugin-react-security
- ソースコードがないのと、更新が3年前なのが気になる
- https://github.com/snyk-labs/eslint-plugin-react-security
- npmにpublishしていないのと、更新が3年前、「The eslint-plugin-react-security project is no longer under active maintenance by the Snyk team.」とあるのが気になる
という状況でした。
一方、React以外のセキュリティについては eslint-plugin-security がありました。
リポジトリのREADMEには
ESLint rules for Node Security
This project will help identify potential security hotspots, but finds a lot of false positives which need triage by a human.
と書かれていましたが、Node.js以外にも使えそうな気がしたことから、ためしてみたときのメモを残します。
目次
- 環境
- eslint-plugin-securityについて
- Reactアプリの作成
- ESLintプラグイン eslint-plugin-security の挙動を確認する
- 余談:ReDoSに対する、ESLintプラグインについて
- ソースコード
環境
- React 18.2.0
- Vite 5.2.0
- ESLint 8.57.0
- eslint-plugin-security 3.0.0
- ReDosに関する他のESLintプラグイン
- eslint-plugin-regexp 2.5.0
- eslint-plugin-redos 4.4.5
eslint-plugin-securityについて
READMEに記載のある通り、セキュリティに関するルールが定義されています。
https://github.com/eslint-community/eslint-plugin-security?tab=readme-ov-file#rules
Node.jsに関するものもありますが、以下の Regular Expression Denial of Service (ReDoS) のように Node.js環境以外でも使えそうなものも定義されたりします。
https://github.com/eslint-community/eslint-plugin-security/blob/main/docs/regular-expression-dos-and-node.md
そこで今回は、ReDoSが発生するコードを実装した時、ESLintプラグイン eslint-plugin-security
がルール違反を検知するか確認します。
Reactアプリの作成
まずは、ReDoSが発生するReactアプリを作成します。
最初に、Vite.jsでひな形となるReactアプリを生成します。
手順としてはVite.jsのドキュメントのままなので、ここでは記述を省略します。
https://vitejs.dev/guide/#scaffolding-your-first-vite-project
次に、メールアドレスに対してバリデーションが行うフォームを作成します。
そのフォームでは
eslint-plugin-security
のドキュメントにある正規表現を使って、メールアドレスに対してバリデーションする- バリデーションの実行時間を計測する
を実装します。
import './App.css' function App() { const handleSubmit = (e: React.SyntheticEvent) => { // https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/ e.preventDefault() const startsAt = performance.now() const target = e.target as typeof e.target & { email: { value: string } } const email = target.email.value console.log(email) // ReDoS が発生するコード const emailExpression = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/ if (emailExpression.test(email)) { console.log("OK") } else { console.log("NG") } console.log(performance.now() - startsAt) } return ( <> <form onSubmit={handleSubmit}> <input type="text" name={"email"} /> <button type="submit">Run</button> </form> </> ) } export default App
Reactアプリができたので、動作を確認します。
フォームの入力値を色々試したところ、文字数が増えるごとに処理時間が増えました。そのため、ReDoSが発生していると分かりました。
ESLintプラグイン eslint-plugin-security の挙動を確認する
ReDoSの発生が確認できたので、次は eslint-plugin-security
の挙動を確認します。
まず、READMEに従い、 eslint-plugin-security
をインストールします。
https://github.com/eslint-community/eslint-plugin-security
$ npm install --save-dev eslint-plugin-security
続いて、プラグインを設定します。
なお、Vite 5.2.0 の時点では .eslintrc.cjs
が生成されるので、READMEの eslintrc config (deprecated)
な書き方で設定します。
module.exports = { // ... extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'plugin:security/recommended-legacy', // 追加 ], // ...
準備ができたのでWebStormでソースコードを開いたところ、該当箇所でESLintがルール違反を検知しました。
これより、 eslint-plugin-security
はReactアプリであってもルール違反を検知すると分かりました。
余談:ReDoSに対する、ESLintプラグインについて
今回調べたReDoSについては、以下に詳しい記事がありました。
正規表現の脆弱性 (ReDoS) を JavaScript で学ぶ
また、他にもいくつかESLintプラグインがあったため、それらがどんな状況だったかをメモしておきます。
eslint-plugin-regexp
こちらは正規表現の誤りやスタイルガイドのESLintプラグインです。
こちらにもReDoSに関するルールはあります。
regexp/no-super-linear-backtracking | eslint-plugin-regexp
ただ、今回のコードの場合、ReDoSのルール以外で検知していました。
そこで、 eslint-plugin-regexp
のドキュメントにあるコードを追加したところ、ルール違反を検知しました。
eslint-plugin-redos
以下の記事や資料を読んで、このプラグインを知りました。
- 資料
- プラグイン
インストールしてためしてみたところ、ESLintがルール違反を検知しました。
eslint-plugin-regexp
向けに追加したコードに対しても、ルール違反を検知しています。
ソースコード
Githubにあげました。
https://github.com/thinkAmi-sandbox/react_and_node_with_eslint-example
今回のプルリクはこちら。
https://github.com/thinkAmi-sandbox/react_and_node_with_eslint-example/pull/1