Node.js向けのアーカイブ展開ライブラリ「tar-fs」で深刻な脆弱性 CVE-2025-48387

セキュリティニュース

投稿日時: 更新日時:

Node.js向けのアーカイブ展開ライブラリ「tar-fs」で深刻な脆弱性 CVE-2025-48387

Node.js向けのアーカイブ展開ライブラリ「tar-fs」で、展開先ディレクトリの外側に任意ファイルを書き込みできてしまう“リンク経由のディレクトリトラバーサル”脆弱性が明らかになりました。GitHub Advisory(GHSA-xrg4-qp5w-2c3w)およびCVE-2025-48387として公開され、深刻度はCriticalです。extract() を直接・間接に使っているプロジェクトは至急アップデートしてください。

影響バージョンと修正版

  • 影響:3.x < 3.0.9、2.x < 2.1.3、1.x < 1.16.5(少なくとも v3.0.8/v2.1.2/v1.16.4 で再現)

  • 修正版:3.0.9/2.1.3/1.16.5

※v3.0.2〜v3.0.8 はシンボリックリンク脆弱性とハードリンク脆弱性の両方に該当し、特に危険度が高いとされています。

脆弱性の概要

攻撃者が細工した tar を展開すると、ライブラリのリンク処理(シンボリックリンク/ハードリンク)検証の不備を悪用して、展開先(cwd)外のパスへ到達し、既存ファイルの内容上書きや新規ファイル作成が可能になります。

PoCでは、/home/username/flag/flag を“展開先とは無関係な場所”にもかかわらず上書きし、/home/username/flag/newfile を作成できることが示されています。

技術的要点

この不具合の肝は、「展開先ディレクトリ配下に収まっているか」を確認する実装が、シンボリックリンク(symlink)とハードリンク(hardlink)の連携技で破られることにあります。extract() は tar エントリの処理中に、リンク先がカレント展開先(cwd)内かどうかを path.resolve() と簡易チェック(inCwd())で判定しますが、ここでは リンクが実在するか/リンク先がどこへ解決されるか までは追跡しません。

攻撃側は noop/…/../../../ のように相対成分を含む 多段 symlink を tar 内に作り、"." へ自己参照するリンクと組み合わせて 見かけ上は cwd 内だが実際には cwd の外へ抜ける経路 を作れます。検証は「文字列としてのパス」を安全そうに見せれば通ってしまうため、ここで最初の防護線が崩れます。

次に ハードリンク作成処理(onlink() の甘さを突きます。

コードは dst = path.join(cwd, path.join('/', header.linkname)) のように 強制的に cwd を前置 して「安全な絶対パス」に見せかけた上で、link(dst, name) でリンクを張ります。しかし name 側が先ほど用意した cwd 外へ通じる symlink 経路 を含んでいれば、表面上は cwd 配下でも実体は外部ファイルを指すハードリンクが成立します。この状態で通常ファイルエントリを書き込むと、同一 inode に対する上書きになり、結果として 展開先外の任意ファイル内容を置換できます。PoC で /home/username/flag/flag が「展開先と無関係なのに上書き」できるのはこのためです。

決定打になっているのが v3.0.2 で入った検証ロジック退行です。以前の validate() は経路の各成分を再帰的に lstat し、途中に symlink があれば失敗として弾いていました。ところが v3.0.2 以降は「直近の親がディレクトリか」しか見なくなり、symlink 配下に“ディレクトリ名らしき成分”を差し込めば検証を通過するようになりました。

これが前段の 多段 symlink による外部到達と噛み合い、v3.0.2〜3.0.8 は symlink 脆弱性と hardlink 脆弱性が同時に成立してしまいます。一方、v2.1.2 と v1.16.4 はこの退行は無いものの、hardlink 側の検証不備が残っているため、symlink を踏み台にした任意場所へのハードリンク→上書きという流れ自体は実現可能です。

影響範囲の大きさ

tar-fs はエコシステム内で広く利用され、依存パッケージ・ダウンロード数はいずれの系統でも数千〜数万の依存と数百万週次DL規模。とりわけ prebuild-install 経由の間接依存が多く、自覚なく脆弱版を取り込んでいるケースが想定されます。