Yarnは超安全?
Tim Kadlec
2016年10月25日
0 分で読めます数週間前、FacebookはYarnをオープンソースとして公開すると発表しました。npmレジストリ向けの新しいクライアントです。一部から懸念の声も上がりましたが、オープンソース開発の好例と言えるでしょう。Facebook、Google、Exponent、Tildeは、標準のnpmクライアントを使ううえで同様の課題を抱えていました。各社がそれぞれ独自に開発するのではなく、協力してnpmを基盤に改善を重ねたのです。その結果、基盤となるnpmレジストリの強みを損なうことなく、注目すべき改良を加えた代替クライアントが生まれました。
Yarnは自らを「超高速」「非常に信頼性が高い」「極めて安全」とうたっています。Yarnが大幅に高速なことが多く、新しいロックファイルによってアプリケーションのインストール時の一貫性が高まるのは事実ですが、セキュリティに関する主張は少々楽観的すぎます。
Yarnがセキュリティのために行うこと
Yarnが「極めて安全」と言うときに指しているのは、チェックサムを使って、要求したパッケージが改変されずに届いたパッケージと同一であることを検証している点です。
チェックサムの検証
プロジェクトの一つでyarn.lockファイルを開くと、その動作を確認できます。以下はその一部です。
上のコードは、momentパッケージを要求し、次のURLに解決されたことを示しています。
ここで特に注目すべきなのは、ハッシュの後に続く部分です。
これはSecure Hash Algorithm 1(SHA-1)で計算されたファイルのチェックサムです。URLからパッケージをローカルにダウンロードすれば、Linuxではsha1sumコマンド、Mac OSXではshasumコマンドを使って、コマンドラインでチェックサムを検証できます。
これらのコマンドはSHA-1ハッシュを出力し、ポリシーファイル内のハッシュと一致します。では、パッケージを要求したものの、yarn.lockファイルのチェックサムに記録されたものと何らかの違いがあったとしましょう。たとえば、README.mdファイルに1行追加し、.tgzアーカイブを作り直してから、もう一度shasumを実行しました。新しいハッシュは次のとおりです。
この新しいハッシュは期待していたものと異なるため、何かが変更されたとわかります。要求したものと受け取ったものが一致していません。この何かは無害な場合もあります。ファイルの転送中にエラーが起こり、破損したのかもしれません。一方で、より悪意のあるケースも考えられます。攻撃者がパッケージを入手し、何らかの方法で改ざんした可能性もあります。チェックサムがあれば問題の発生を把握でき、さらに調査を進められます。
攻撃者はどうやってパッケージを改ざんするのか?
データの完全性を確保するのは確かに有用な機能ですが、そもそも攻撃者がどうやってパッケージを改ざんするのかを考えてみる価値があります。
方法の一つは、パッケージをホストするレジストリで、ソースから改変することです。ほとんどのユーザーはnpmjs.comからパッケージをダウンロードしています。私の知る限り、レジストリ上で攻撃者がコードを改変した事例はありません。
もう一つの可能性は、ダウンロード中にパッケージを転送経路上で改変することです。ここでも、ほとんどのパッケージはHTTPSを使用するnpmのパブリックレジストリからダウンロードされます。HTTPS経由で転送中のパッケージを改変することは可能ですが、簡単ではありません。
チェックサムは、自社でリポジトリをホストする場合に、より役立ちます。ArtifactoryやNexusのサービスは十分に安全ですが、自前で構築する場合は、セキュリティの弱点を突かれてレジストリ上のパッケージが直接改ざんされる可能性があります。また、(強く)推奨はしませんが、HTTPで配信されているローカルレジストリを見たこともあります。こうした状況ではパッケージの改変がはるかに容易になるため、チェックサムの重要性も高まります。
npmのパブリックレジストリを使う場合や、商用サービスでHTTPS経由の自社レジストリをホストする場合、チェックサムが防ぐ改ざんのリスクはそれほど大きくありません。これはセキュリティ機能ではありますが、重要度は高くありません。
固定バージョンのためのyarn.lock
さらに、yarn.lockファイル自体が、セキュリティ対策に新たな課題をもたらします。npm shrinkwrapと同様に、yarn.lockファイルの目的は、依存関係の特定のバージョンを固定することです。ロックファイルを使う利点は、Yarnプロジェクトを自分のマシンにインストールし、翌日に同じアプリケーションを本番環境へインストールした場合、新しいバージョンがリリースされていても、両方の環境でまったく同じ依存関係が使われるとわかることです。
一貫性を保つには便利ですが、ロックファイルは使用中のパッケージを更新しない方向に働きます。semverの範囲指定を使う場合とは異なり、依存関係を新しいバージョンにアップグレードするには、ロックファイルを編集するか作り直すしかありません。そのため、重大な脆弱性の修正を含む更新がないか、開発者自身が注意して確認する必要があります。これは、package.jsonで採用されているようなsemverベースの方法以上に重要です。
だからといって、ロックファイルを使うべきではないということではありません。アプリケーションに一貫性が必要なら、ぜひ使ってください。ただし、安全でないパッケージを継続的に確認し、更新するための適切な手順を整える必要があることを忘れないでください。
欠けているセキュリティ対策
チェックサムはセキュリティの層を一つ加えますが、取得しようとしている元のパッケージ自体が安全であることは保証しません。オープンソース開発の世界では、それこそがはるかに大きな問題です。オープンソースのメンテナーの多くは善意で取り組んでいますが、セキュリティを中核的な要件としてパッケージが開発されることはまれです。こうしたパッケージを自分たちのプロジェクトに取り込むとき、依存関係がすべて把握できているわけでも、潜在するセキュリティ上の問題を理解しているわけでもないまま、無防備に利用してしまいます。
たとえば、先ほど取り上げたmomentパッケージには、修正プログラムが提供されている正規表現によるサービス拒否の脆弱性があります。Yarnでパッケージをインストールしても、それはわかりません。既知の脆弱性がないか依存関係をスキャンすることは、Yarnが解決する問題とは別の、より大きなセキュリティ課題です。
本当に「極めて安全」になるには?
幸い、Yarnはnpmを基盤にしているため、エコシステムとの親和性は高いです。現時点ではYarnにいくつか課題がありますが、解決されていけば、既存のセキュリティツールも最小限の変更で使えるはずです。
たとえば、npmパッケージの既知の脆弱性に対処するため、Node.jsアプリケーションのpost-installステップでsnyk protectを実行することを推奨しています。yarn installを実行してもこのステップは実行されるため、snyk protectが引き続き依存関係をスキャンし、既知の脆弱性を検出します。
Yarnはとても優れたツールだと考えています。これだけ注目を集めていることからも、同じように感じている人は多いでしょう。多くの場合、より高速です。また、新しいロックファイルは、インストールの一貫性を高めたい多くの組織にとって役立つはずです。
Yarnが最初からセキュリティを組み込もうとしているのは素晴らしいことです。しかし、自らを「極めて安全」と表現するのは少々自信過剰です。問題はチェックサムではなく、マーケティングの表現にあります。チェックサムはデータの完全性を保つのに役立ちますが、Node.jsのエコシステムでは比較的小さな問題です。それよりはるかに重要なのは、依存関係そのものが安全であることを確認することです。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。