'.' in @INC問題とその対処法について(2017年3月版)

YAPC::HokkaidoやYAPC::Kansaiで話した通り、Perl 5.26ではセキュリティ上の問題で@INCにカレントディレクトリが含まれなくなります。p5pやツールチェーン側ではその影響を軽減すべくCPANクライアントやTest::Harnessに従来の挙動を残すような仕組みを用意中ですが、現時点ではまだすべての対策が出そろっているわけではありません。最終的にどうすべきかは5月に開催される予定のPerl Toolchain Summit (旧Perl QA Hackathon)後にあらためてまとめるつもりですが、直接的な影響を受けるCPAN Authorのところには順次バグレポートが届いているかと思いますので、可能であれば以下の対応をご検討ください。

incディレクトリなどにMakefile.PL/Build.PL用の特殊なモジュールなどを同梱している場合

カレントディレクトリが@INCから消えることで、開発時および手動インストール時にはinc::Module::Install、inc::MyBuilderなどの同梱モジュールが正しく読み込めなくなる可能性があります。この辺は別途パッチがあたる可能性もありますが、基本的にはMakefile.PL/Build.PLなどの先頭付近に適宜以下のような行を追加しておいていただけると面倒がなくてよいかと思います(通常のインストール時にはCPANクライアント側で対策が取られるので問題にはならないはずです。また、どうせ開発するのは自分だけだから、perl -I. Makefile.PL/Build.PLするよ、という方もひとまず気にしなくてかまわないかと思います。ただ、CIがこけたりCPAN Testersなどから指摘を受ける可能性はあります)。なお、Makefile.PL/Build.PL については use lib "."; でもよいはずですが、今回の「対策」と呼ばれるものは "." を狙い撃ちにしているので、場合によってはおかしな副作用に巻き込まれる可能性があります。

use FindBin;
use lib $FindBin::Bin;

また、Module::Installについては、Perl本体あるいはツールチェーン側で何らかの特別対応が行われる可能性もあるのですが、最新のModule::Installにも警告が出ている通り、これまでにもいろいろと問題が出ていますので、特に最新版をお使いでない方は、可能であればこの機会にMinilla、Dist::Zilla等のオーサリングツールに移行しておいていただけると助かります。

テストファイル中で t::Foo のようなモジュールを呼んでいる場合

これも、面倒でなければ、上と同じく各テストファイル中でFindBinを呼んで、実際の階層に応じたlib設定をしておいてください。

また、修正すべきファイルが多すぎて大変な場合は、依存モジュールにTest::Harnessの3.38以降を加えておけば、とりあえずmake test時には@INCにカレントディレクトリが戻るようになります。

これも同じくどうせ自分だけだから…という考え方もありですが、Makefile.PL/Build.PLの場合と同様におそらくCIでこけたり、CPAN Testersから指摘を受けることになるかと思います。

do "localfile.pl" のような呼び出しをしている場合

CPANモジュールには少ないと思いますが、お手元のアプリやスクリプトで環境設定などのために do を使ったファイル読み込みをしている場合は do "./localfile.pl"; のように明示的にディレクトリを追加しておいてください(もちろんFindBinを利用してもかまいません)。

また、require "jcode.pl"; のような行も、あれば同様の修正をお願いします(もっとも、jcode.plについてはそのままだとそもそも5.26では読み込み時にエラーになりますが)。

スクリプトをインストールするディストリビューションの場合

インストール時に bin/foo(.pl) のようなスクリプトをインストールするディストリビューションについては、追加の対策をしておいた方がよいかもしれません。コアに入っているものについてはいまのところスクリプトの先頭付近に以下のような行が追加されていますが、これについてはno lib "."; の方がよいという異論もあります(no lib "." なら明示的な perl -I. も封じることができますが、-I オプションを使える状況ならどちらにしても迂回できるので現状ではそれほど違いを気にする必要はないかと思います)。

BEGIN { pop @INC if $INC[-1] eq '.' }

なお、この行は基本的にはスクリプトやアプリの先頭付近に一度追加すれば十分です。

やってはいけないこと

use lib "."; は探索パスの「先頭」にカレントディレクトリおよび関連ディレクトリを追加してしまうので、うかつに使うとかえって発端となった脆弱性の影響を受けやすくなってしまいます。私的なスクリプトなどの応急処置には便利ですが、一般に公開するモジュール、アプリなどでは使用を避けてください。シェルスクリプト/バッチファイルなどから呼び出すperlコマンドラインオプションに「-I.」を追加するのも同様の理由で危険です。

なお、CPANモジュールを使うだけの方は、5月のPerl Toolchain Summit以降にCPANクライアント(とTest::Harnessあたり)を最新にしておいていただければ、ほぼ問題なく5.26に移行できる(ようになる)見込みです。