JavaScriptの静的構文チェッカーといえば、一昔前までは JSLint一択でしたが、一昨日にも書いたように、二番手のJSHintに追い上げられ、首位の座も風前の灯というところです。
JSLintは、名著 “JavaScript: The Good Parts”(邦題『「良いパーツ」によるベストプラクティス』)を著したDouglas Crockford氏の書いた構文チェッカーで、”The Good Parts”に書かかれている”Bad Parts”を厳密にチェックします。
ただ、あまり厳密過ぎて JSLint に完璧に従うのは難しく、実際上それほど厳密に順守しなくても良い項目も含まれています。JSLintの便利なところは、自分にとって不要と思われるチェック項目を個別にオフにできることで、ソースコードの先頭にオフにしたいオプションを書いておけばチェックされません。
私も10項目ぐらいはオフにしていて、その中の一つが正規表現についてのチェックです。
/*jslint browser : true, continue : true, devel : true, newcap : true, nomen : true, plusplus : true, regexp : true, sloppy : true, vars : true, white : true */ /*global jQuery */
デフォルトの JSLint は、正規表現中のピリオド「.」(任意の一文字にマッチする)と文字クラスの否定に使われる「^」に対してセキュアでないと警告を発します。
この二つを禁止されると正規表現を書くのは大変、というか書けないので常にオフにしているのですが、かねがね、なんでこれを禁止しているのか不思議に思っていました。
まぁ理由については “The Good Parts” のどこかに書いてあるんでしょうが、StackOverFlowをザッピングしているとたまたま以下のようなQ&Aを見つけました(以下、簡訳です)。
リンク元:
Purpose of JSLint “disallow insecure in regex” option (JSLintの「安全でない正規表現を許可しない」オプションについて)
(質問)Jon Bringhurst氏:
numExp = parseInt(val[1].replace(/[^\-+\d]/g, “”), 10); というコードを通すと JSlint は次のエラーを吐く。 Lint at line 604 character 48: Insecure ‘^’. このエラーメッセージは、JSLint のオプションページの以下の説明に関係しているようだ。 “true if . and [^…] should not be allowed in RegExp literals. どこまでやったとしてもクライアントサイドの JavaScript アプリケーションを完璧にセキュアにできるとは私には思えない。実際のところどんなに完璧な正規表現でも、firebugかなにかで値をいじることはできる。厳しいバリデーションはサーバサイドでこそ必要なもので、クライアントサイドのブラウザでは、普通のユーザが間違えそうな項目のバリデーション程度で充分ではないかと思う。 このエラーは無視してもだいじょうぶだろうか?それとも私は何か、クライアントサイドのバリデーションで起こりうるような危険性を見落としてるだろうか? |
(回答)Tomalak氏:
ここで「安全ではない」というのは「具体的でない」ということだ。ピリオド”.”と文字クラスを否定する[^…]は、どちらも正規表現中で実際にどんな文字にマッチするのかが明確ではない。バリデーションが目的の場合、こうした正規表現には想定外の入力、あるいは望ましくない入力を通してしまうというリスクが潜んでいる(ブラックリストに入れるかホワイトリストに入れるか判定するようなケースを考えてみよう)。 いずれにせよピリオドも文字クラス否定の「^」も正規表現としては有効な要素だ。(今回のような)必要があって使っている場合、私もこの警告は過剰だと思う。 悪意あるユーザはいつでもサイトの穴をさぐっている。この警告はそうした「正規」でない操作に備えたものと言えるだろう。 |
胃にすとんと落ちる、というほどではないですが、まぁ納得できる説明です。
サーバなどでビジターの入力をチェックするバリデーションのコードで「.」を使うのは脆弱性の原因になりうるので「Bad Parts」に分類されているわけです。
クライアントで、通常の文字処理に使う分にはまず問題はない、ということのようです。
(2012/12/27 19:59 投稿)
Pingback: JSLintオプション解説「. and [^...] in /RegExp/」|もっこりJavaScript|ANALOGIC(アナロジック)