Diary?

2009-09-18
Fri

(17:04)

Python でマルチバイト文字列を扱うための Tips として sitecustomize.py でデフォルトのエンコーディングを指定しろというものがある。これは Python のライブラリパスの通ってるところに sitecustomize.py というファイルを置き、

import sys
sys.setdefaultencoding('...')

とやるというものだが、これをやるとプログラムが自分の環境に依存してしまうのでよくない。というか、かなりの間これに気がつかずに Caty の開発を進めていて、檜山さんからのバグレポでようやく気がついたという割とトホホな事がついさっきあった。

そういや UTF-8 の冗長表現によるセキュリティ問題についてだが、まず前提として Python は文字列(ってかバイト列)を Unicode にするときに冗長表現の UTF-8 はエラーにして叩き落とすようになっている。なので、外部から入力されたデータに対しては Unicode を適切な場所で使うことで問題はなくなる。そして

  • Caty は文字列をすべて Unicode に変換する
  • ユーザが書くプログラムには必ずスキーマを付け、そこで扱うデータの型を宣言する
  • スキーマを宣言しないと、どうやってもデータを受け取れない
    • 例えばフォームから foo という名前で文字列を受け取る場合、 {"foo": string} のような JSON スキーマが必須
    • 文字列ではなくバイト列として扱いたい場合、 binary 型で宣言しないとダメ
      • ちなみに binary 型の戻り値を string 型の引数を取る処理に渡すと、今のところ自動で Unicode に変換してる。理想を言えば型エラーなのだが、それやるには型推論と検証を実装しないとダメな事が発覚した(any 型とか型変数へ対応する必要性が発覚した)のでペンディング

という仕様になっているので、うっかり Unicode に変換せずに文字列を通してしまってバグやらセキュリティホールを作り込むという事態にはなりにくくなっている。流石に文字列が必要なところに binary を指定するミスは、うっかり Unicode に変換忘れよりは頻度は大きく少ないだろう。

あと Caty のテンプレートエンジンは VM レベルで特殊文字のエスケープを行うようにしている。これはエスケープ用の命令があるわけではなく、テンプレートに埋め込む情報の出力命令がエスケープ処理を行っているということ。テンプレートエンジンのフロントエンド(文法)はいくらでも追加可能だが最終的に吐き出されるコードの処理系は共通なので、やはり原理的に XSS などの脆弱性は作り込みにくくしてある。

まだ構想段階なのも含め、かなり Caty はいろんな仕様を安全側に倒すようにしてある。もっとも、最初のリリースでどこまでできるかは未知数だが。

Creative Commons
この怪文書はクリエイティブ・コモンズ・ライセンスの元でライセンスされています。引用した文章など Kuwata Chikara に著作権のないものについては、それらの著作権保持者に帰属します。