HTTP::Engine::Middleware::Staticのdocrootにシンボリックリンクを渡してはいけない
Arkでstaticなファイルが表示できないことがあるので何かと思ったら、HTTP::Engine::Middleware::Staticのdocrootにシンボリックリンクを渡していたのが原因でした。CPAN最新版のHTTP::Engine::Middleware 0.17で確認したけど、githubの最新版でも該当部分は同じなので再現するはず。OSはLeopard。
HE::Middleware::Staticはbefore_handle()内で
my $docroot = dir($self->docroot)->absolute;
としてdocrootを取得した上で、
my $realpath = Cwd::realpath($file->absolute->stringify); if ($realpath) { # check directory traversal if realpath found return HTTP::Engine::Response->new( status => 403, body => 'forbidden') unless $docroot->subsumes($realpath); }
としてディレクトリトラバーサルの対策をしていますが、$realpathがrealpathを取っているのに対して、$docrootはrealpathではないので、シンボリックリンクを渡すとsubsumesが期待通りの判定をしてくれないケースがあります。
対策としては、$mw->installする時にdocrootにrealpathを投げるか、HE::Middleware::Staticがdocrootを取得する部分を
my $docroot = dir(Cwd::realpath($self->docroot))->absolute;
に書き換えるとか。
# テストも書いてパッチをpull requestしました。経過待ち。