2013年07月

「正しい入力」「あり得る入力」「あり得ない入力」の話

メールアドレスとかの具体例を挙げていますが、一般論としては入力仕様が定義され、正しく理解していれば、自ずと「正しい入力」は定義できます。「正しい入力」以外がエラーとすべき物としか

Twitter / yohgaki: メールアドレスとかの具体例を挙げていますが、一般論としては入 ...

私ならバリデーションエラー(あり得ない入力)と入力ミス(あり得る入力)の区別ができないプログラマは要りません。

Twitter / yohgaki: 私ならバリデーションエラー(あり得ない入力)と入力ミス(あり ...

「正しい入力」「あり得る入力」「あり得ない入力」の区別はおもしろいと思った。

一般に、フォームからの入力が正しくなかった場合、レスポンスは「入力時のフォームの再現+エラーメッセージ」とすることが多いだろう。このとき、ユーザの入力値はそのまま表示させたい。だが、たとえばセレクトボックスについて考えると、オプションに存在しない入力値がリクエストされた場合に、入力時のフォームを再現できなくなる。月(1〜12)を選択するはずのセレクトボックスの入力値が「13」だったら、どのようなレスポンスを返せばよいのか。その場合、「13」は「あり得ない入力」とみなし、不正なリクエストである旨のみを知らせるレスポンスを返す、という考え方もあってよいのではないだろうか。

この考え方を実現しようとすると、「正しい入力」「あり得る入力」「あり得ない入力」を明確に区別する仕様が必要になる。月を入力するインターフェースがセレクトボックスではなくテキストボックスだったら、「13」は「あり得る入力」としなければならない。単なる入力ミスなのに、入力時のフォームが再現されず、不正なリクエストである旨のみ知らされても、ユーザは困ってしまう。

なお、バリデーションと呼ばれるのは、「正しい入力」と「正しくない入力(あり得る入力+あり得ない入力)」を判別する処理のことだろう。ならば、「あり得る入力」だって、バリデーションエラーということになる。いや、「あり得ない入力」とそれ以外を判別するのがバリデーションだというのであれば、「正しい入力」と「正しくない入力」を判別する処理は何と呼べばよいのか。

Rails4セキュリティ レボリューションズ

Strong Parametersは仕組みとしてコントローラで入力パラメータのバリデーションを推奨。

params.require(:user).permit(:name, :email)
my_params_validate(params) 

または

paramsオブジェクトからバリデーションメソッドを呼ぶ様に拡張

params.require(:user).permit(:name, :email).validate(self)
  1. 「コントローラで入力パラメータのバリデーションを推奨」している大垣さんにとって、Strong Parameters がそれっぽいものに見えた
  2. これはよいものだと講演で取り上げた
  3. しかし、実際には単なるフィルタだった(大垣さんが定義するところのバリデーションではなかった)
  4. バリデーションメソッドを別途追加しなければ辻褄が合わなくなった

という流れ。

とはいえ、こうしたメソッドをRailsコアチームに提案して、首尾よく実装されたら、それはそれで素敵なことだと思う。

追記(2013-07-19)

おおもとのスライドの28ページに、「追加するだけ」との吹き出しを伴って、.validate(self) の記述が追加された。

「追加するだけ」といえばそうなのだろうが、そのようなメソッドを自前で追加しなければならないこと自体、「コントローラで入力パラメータのバリデーションを推奨」などされていない証拠ではないのか。

いずれにしても、Strong Parameters が、大垣さんの想定するバリデーション処理でないことはもはや明らかだ。バリデーション処理でない Strong Parameters がコントローラに組み込まれたからといって、どうして「仕組みとしてコントローラで入力パラメータのバリデーションを推奨」などといえるのか

現に、Integrate strong_parameters in Rails 4 by guilleiguaran ・ Pull Request #7251 ・ rails/rails ・ GitHub を見れば、モデルによるバリデーションに、DHHが不満を感じていないことが分かる。

「脆弱性対策はミクロな範囲で確認できることが望ましい」の話

パストラバーサル脆弱性対処のためのファイル名の確認は、ファイルをオープンする直前(ファイル名を使う直前)に行うべきだ、という考え方

もう入力値検証はセキュリティ対策として *あてにしない* ようにしよう - 徳丸浩のtumblr

この考え方、つまり「脆弱性対策はミクロな範囲で確認できることが望ましい」という考え方(以下「ミクロ派」)に、ぼくは共感します。徳丸さんが記事の最後でまとめられているとおり、「入力値検証による脆弱性対策は、検証と脆弱性発生箇所が離れるので、確認がしにくい」ためです。

冒頭に引用した「ファイル名の確認」の例においては、「確認の第一歩として文字エンコーディングの妥当性検証が必要になる」というのがミクロ派、「そんなの入口でやればいいじゃん」というのがマクロ派です。少なくともぼくの理解ではそう。

2009-09-10に、以前のブログで書いた「不正な文字列をどこでチェックすべきか」でも、ぼくはミクロ派の立場に立っていました。当時いただいたはてブコメントは、マクロ派のご意見ばかりだったんですよ。

追記

もし不正な文字エンコーディングがブロックされていることが保証されていれば、入口以外での文字エンコーディングチェックを省力することはありだと思います

Twitter / ockeghem: ただし、さっきの話、PHPの場合はそうなんだけど、もし不正な ...

異存なしです。

もしぼくが省力化したくなったら、入口以外では「validな文字列型」や「フォルダ名型」で扱うと思います。不正なバイト列であれば、インスタンス化できなくすればよいわけです。これなら、ミクロ派のぼくでも安心です。

型のない言語は使いません。

プロフィール
知識欲と謎解き欲が旺盛なWebエンジニア。AWS認定ソリューションアーキテクト - アソシエイト。JAPAN MENSA会員
記事検索