2.0〜2.2.26(LTS)・2.3〜2.9.5(mainline)2.2.27(LTS)・2.9.6以降(mainline、2.9.7でregression fix追加)PHPのデファクトパッケージマネージャ「Composer」に2件の重大なコマンドインジェクション脆弱性が発見された。Composer内部の Perforce VCSドライバコード(src/Composer/Util/Perforce.php)でシェルコマンドを構築する際に入力エスケープが抜けており、悪意ある composer.json やリポジトリメタデータから任意コードが実行される。
🔍 混同注意: 本CVEは Composerに同梱されているPerforce連携ドライバ の脆弱性であり、Perforce社が提供する Perforce Helix Core(P4)サーバー自体 の脆弱性(例:CVE-2023-45849など)とは別物です。つまり「Perforceサーバーを運用しているか否か」は関係なく、PHP開発者が使うComposer本体に存在するシェルインジェクションの問題です。実際、GHSAには「Perforceがインストールされていなくても悪用可能」と明記されています。
特に CVE-2026-40261(CVSS 8.8、ネットワーク攻撃可) は深刻だ。攻撃者が用意したComposerリポジトリからパッケージをインストールするだけで、ローカルマシンに Perforceがインストールされていなくても 任意コマンドが走る。--prefer-source オプション使用時や dev-prefix バージョン(dev-main 等)のインストール時が特に危険な状況だ。
本脆弱性はGitHub Security AdvisoriesにGHSA-gqw4-4w2p-838qおよびGHSA-wg36-wvj6-r67pとして公開され、メンテナのJordi Boggiano(Seldaek)自身が即日パッチ版2.2.27/2.9.6をリリースした。発見者はkodareef5とSaku0512の両セキュリティ研究者。
composer.json で Perforce source type を使用していないため、通常利用では本脆弱性のトリガーとなるコードパスに到達しません。両CVEともComposer内部の Perforce クラスに存在するシェルコマンド組み立て処理が原因だ。
Perforce::syncCodeBase() のエスケープ抜けPerforce::syncCodeBase() メソッドが $sourceReference パラメータを エスケープせずにシェルコマンドへ連結 していた。source.reference フィールドは本来、Perforceのチェンジリスト番号やラベル名が入る想定だが、そこにシェルメタ文字(;・&・バッククォート・$() など)を入れられる。
公式advisory本文(Seldaek記述):
The
Perforce::syncCodeBase()method appended the$sourceReferenceparameter to a shell command without proper escaping, allowing an attacker to inject arbitrary commands through a crafted source reference containing shell metacharacters.
致命的なのは「Perforceがインストールされていなくても攻撃が成立する」点だ。Composerは構築したコマンドを実行しようとするため、Perforceバイナリがローカルに存在するかどうかは関係ない。シェルに渡された時点で任意コマンドが走る。
Perforce::generateP4Command() の接続パラメータ注入こちらは Perforce::generateP4Command() メソッドが Perforce接続パラメータ(port・user・client) を補間する際にエスケープを行っていない問題。composer.json の repositories 配列にPerforce型リポジトリを書き込み、そのportやuserフィールドにシェルコマンドを混入できる。
こちらはVCS repositoriesが root composer.json または設定ディレクトリ(~/.config/composer/composer.json)からしか読まれない仕様により、依存パッケージ経由では悪用不可という限定がある。代わりに、攻撃者が作ったプロジェクトに含まれる composer.json を実行するケースで発動する。
composer install 一発でRCECVE-2026-40261の攻撃フローは以下のように成立する。
攻撃の現実的な発動条件:
--prefer-source を明示指定しているdev-main・dev-master など)をインストールpreferred-install: source を設定ファイルで指定しているdev-prefixバージョンは デフォルトでsourceが優先されるため、開発中のPHPプロジェクトでは非常に多くのユースケースで攻撃面が開いている。
公式GHSAはRCE成立時の挙動を 「command execution in the context of the user running Composer」(Composerを実行したユーザーと同じ権限でシェルコマンドを任意実行)と明記している。CVSS Scope は S:U(Unchanged)のため権限の自動昇格はないが、開発者ユーザーの権限で読めるものはすべて読まれ、書けるものはすべて書き換えられると想定すべきだ。
⚠️ 本記事執筆時点(2026-04-14 20時JST、advisory公開約3時間後)で公開PoCは確認されていない。以下は「任意コード実行が成立したRCEが過去どう悪用されてきたか」に基づく想定被害であり、本CVEで実際に観測された攻撃ではない。
任意コマンド実行が走ると、Composerを実行したユーザー権限でアクセスできる資産はすべて攻撃対象になる。以下は過去の同種RCE事例で実際に起きてきた悪用パターン:
| 悪用カテゴリ | 具体的な被害 | 根拠となる過去事例 |
|---|---|---|
| 認証情報の窃取 | ~/.ssh/id_rsa・~/.aws/credentials・~/.gitconfig・.npmrc・.git-credentials を外部サーバに送信 |
Codecov Bash Uploader事件(2021) |
| ブラウザデータ窃取 | Chrome/Firefoxのログイン情報DB・Cookieを抽出 | 各種info-stealerマルウェア |
| 永続化(バックドア) | cron・launchdデーモン・.zshrcへの追記で再起動後も常駐 |
event-streamインシデント(2018) |
| 暗号資産マイナー設置 | バックグラウンドで採掘プロセス常駐・CPU占有 | 過去多数のnpm/Composer系インシデント |
| 横展開の足がかり | 社内ネットワークのスキャン・他サーバへの認証試行 | SolarWinds型サプライチェーン攻撃 |
開発者マシンは 本番クラウドへのアクセス権限を持つ ことが多いため、一度RCEが成立すると本番環境侵害に直結するケースが多い。特にAWSプロファイルが複数設定されている環境は要注意。
CI/CDは「開発者マシンより権限が強い」ケースが多く、被害が跳ね上がる:
GITHUB_TOKEN・NPM_TOKEN・デプロイキー・AWS STS認証がすべて読み出される公式PoCは未公開だが、GHSA記載の「source reference with shell metacharacters」という表現から、攻撃者が仕込む composer.json の構造は以下のような形と想定される(あくまで仕組みの説明のための例示):
{
"repositories": [
{
"type": "perforce",
"url": "p4://example.com",
"depot": "example",
"branch": "main"
}
],
"require": {
"example/package": "dev-main"
}
}
Composerが Perforce::syncCodeBase() 内で組み立てる p4 sync //...@$reference や、Perforce::generateP4Command() で組み立てる p4 -p $port -u $user -c $client ... の各パラメータにシェルメタ文字が入ると、セミコロンやバッククォート以降が別コマンドとしてシェルに渡る。この構造は過去の CVE-2021-29472(Composer Mercurial RCE)や CVE-2024-35241(Composer git branch injection) と同じパターンだ。
CVSSベクトルは両CVEとも UI:R(User Interaction Required)——つまり攻撃者だけで被害は発生せず、被害者が以下いずれかの操作を行う必要がある:
composer install・composer update・composer require を実行するこの「UIが必要」という条件は実効的にはほぼ意味がない——PHP開発者は毎日のように composer install を打つし、CIも自動で走る。攻撃者から見れば「悪意あるパッケージをPackagistや独自リポジトリに上げておく → あとは時間が解決する」という状況だ。
| 項目 | CVE-2026-40261 | CVE-2026-40176 |
|---|---|---|
| 脆弱メソッド | Perforce::syncCodeBase() |
Perforce::generateP4Command() |
| CVSS 3.1 | 8.8 High | 7.8 High |
| 攻撃ベクトル | Network (AV:N) | Local (AV:L) |
| 攻撃面 | 悪意あるパッケージリポジトリ | 悪意ある composer.json |
| 依存経由悪用 | ✅ 可能(任意リポジトリ配信で) | ❌ 不可(rootのcomposer.jsonのみ) |
| トリガー条件 | --prefer-source または dev-prefix |
悪意あるプロジェクトでComposer実行 |
| Perforceバイナリ要否 | 不要(注入成立するだけで発火) | 不要 |
| 発見者 | kodareef5 | Saku0512 |
CVE-2026-40261の方が 攻撃範囲が広く深刻度も高い。Packagist(Composerの公式パッケージリポジトリ)外のカスタムリポジトリを利用している企業や、プライベートレジストリ運用中の組織は特に注意が必要だ。
本CVEの影響範囲は「Composerを使うPHPプロジェクト全部」と広範のため、開発者個人・CI/CD担当・本番運用・セキュリティ管理者の立場別に必要な対応を整理する。以下のチェックリストを順に潰していけば、組織として必要な措置がすべて完了する。
全PHP開発者が最初に実行する項目。手元のComposerが脆弱版かを確認し、即座にパッチ版へ更新する。
# 1. 現在バージョン確認
composer --version
# 例: "Composer version 2.9.5 2026-02-15 XX:XX:XX" ← 脆弱
# 2. mainline系なら最新に
composer self-update
# 2.2 LTS系を固定運用している場合
composer self-update --2.2
# 3. 更新後の再確認(2.9.6以降 または 2.2.27 が表示されればOK)
composer --version
5分以内にできる作業です。後回しにしないこと。dev環境で composer install を走らせる予定がある人は、更新前に絶対にコマンドを実行しないでください。
💡 2.9.7について: 2026-04-14 11:36 UTC(2.9.6の約2時間後)にリリース済み。セキュリティ修正ではなく、2.9.6に混入した軽微なregression(「Composerコマンドのサブストリングと同名のスクリプトエイリアスが呼べない」問題 #12802)を修正する純粋なバグフィックス。セキュリティの観点だけなら2.9.6で十分だが、カスタムスクリプトを多用するプロジェクトは 2.9.7以上が推奨。
ローカル環境だけでなく、CI/CD・本番デプロイパイプラインで動くComposerも同じく脆弱。こちらは「一斉更新」が必要になる。
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- tools: composer:2.9.5
+ tools: composer:2.9.6
バージョン指定をしていない場合(tools: composer のみ)は最新版が引かれるため自動的に2.9.6となる。ただしDockerイメージ経由の場合はキャッシュされた古い版が使われ続けるので、次の項目も実行すること。
# Before(脆弱)
FROM composer:2.9.5
# または
FROM composer:2
# After(推奨)
FROM composer:2.9.6
# もしくはタグなしで常に最新
FROM composer:latest
既存のDockerビルドキャッシュに古いComposer版が入っている可能性があるため、--no-cache でリビルドしてから本番デプロイすること。
docker build --no-cache --pull -t myapp:latest .
本番サーバー上で composer install --no-dev を実行するタイプのデプロイをしている場合、サーバー上のComposer自体を更新する必要がある。
# サーバーへSSH後
sudo composer self-update
# またはrootで走らない運用なら
composer self-update --install-dir=/usr/local/bin
composer --version # 2.9.6 または 2.2.27 を確認
Ansible・Chef・Terraformなどで管理している場合は、プロビジョニングスクリプトのComposerバージョンピンも同時に更新すること。構成管理ツールが古い版を再度インストールして上書きしてしまう事故を防ぐ。
直近の攻撃可能性を監査し、再発防止策をプロジェクトに組み込む。
composer.json / composer.lock の棚卸しperforce タイプのリポジトリ定義が含まれていないかをgrepで確認する。Perforceを使っていない組織は本来入っているはずがないため、もし見つかれば既に何かが仕込まれている可能性がある。
# プロジェクト全体で perforce 型リポジトリを探す
grep -rn "\"type\": *\"perforce\"" . --include="composer.json"
# ソース設定の不審な値もチェック
grep -rn "\"source\":" . --include="composer.json" | grep -Ei "perforce|p4"
preferred-install: dist を恒常設定化Composerを最新版に保っても、将来類似の脆弱性が出たときにsource優先設定だと攻撃面が開いたままになる。「VCSからsourceでダウンロードする必要性がない」プロジェクトは、dist優先を設定ファイルに書き込むのが正攻法。
{
"config": {
"preferred-install": "dist"
}
}
または全プロジェクト共通の設定として:
composer global config preferred-install dist
Packagist公式以外の カスタムリポジトリ(企業内Satis・Private Packagist・GitLab Package Registry等)を使っている場合、そのインフラの侵害が即RCEに直結する。以下を確認:
Composer 2.4以降には composer audit コマンドが搭載されている。GHSA連携で既知脆弱性を検知できる。
# .github/workflows/ci.yml に追加
- name: Composer audit
run: composer audit --no-dev --format=json
これで今後同様の脆弱性が公開された時、CIが自動的に警告を出すようになる。
セキュリティチーム・CTO・開発リードは、以下の社内通達と監視体制を整備する。
Slack・社内Wiki・メールで以下のテンプレートを展開:
【至急】PHP Composer脆弱性対応(CVE-2026-40261/40176)
■ 影響: Composer 2.0〜2.2.26 および 2.3〜2.9.5
■ 対応期限: 本日中
■ 作業:
1. 各自の開発機で `composer self-update` を実行
2. 2.9.6 または 2.2.27 になっていることを確認
3. CI/CD・Dockerイメージを更新してデプロイ
■ 緊急回避策(更新できない場合):
`composer install --prefer-dist` を使う
■ 参考: https://github.com/composer/composer/security/advisories/GHSA-gqw4-4w2p-838q
シェル実行ログやEDR/XDRで、以下のパターンが出た場合は攻撃試行の可能性がある:
sh -c・bash -c・curl・wget 等)composer install 実行直後のネットワークアウトバウンド増加composer.json の repositories フィールドに "type": "perforce" を含むコミット今回の事件を機に、組織として以下を再点検:
composer require しない運用ルールcomposer.json・composer.lock 変更の人間レビュー必須化どうしても即座に更新できない事情がある場合(変更凍結期間中・レガシー環境の制約等)は、以下のワークアラウンドで攻撃面を縮小できる。ただし根本解決ではないため、できるだけ早くComposer自体の更新に切り替えること。
# インストール時にdistを強制(sourceによる脆弱コード実行を避ける)
composer install --prefer-dist
# 既にstate restored済みのcomposer.lockがある場合も
composer update --prefer-dist
設定ファイルに書く場合:
{
"config": {
"preferred-install": "dist"
}
}
公式advisoryのWorkaroundsには「信頼できるComposerリポジトリのみを使用する」とも記載されているが、これは補助的な対策に過ぎないことに注意。過去にはPackagist公式自体がサプライチェーン攻撃の対象になった事例(2021年のAPIトークン問題、2022年のctx/PHPass乗っ取り等)があり、「信頼できるリポジトリなら絶対安全」は成立しない。また正規リポジトリに正規ユーザーとして公開された個別パッケージが悪意を持つ可能性も排除できない。最終的な根本解決は必ず パッチ適用(2.9.6以降 / 2.2.27) で行うこと。
2026年に入り、開発ツール・パッケージマネージャ系のCVEが加速している。直近の大きな事例:
「開発者マシン/CIを攻撃面として狙う」攻撃が2026年Q1から明確に増加している。Composer・npm・Dockerという「毎日動くツール」の脆弱性は、直接ユーザーを攻撃するよりも広い被害を引き起こし得るため、開発者側の脆弱性監視・即時パッチ適用が今後さらに重要になる。
composer self-update今回のCVE-2026-40261/40176は、Composerというデファクトツールに存在した典型的なコマンドインジェクション脆弱性だ。特にCVE-2026-40261は Perforce未インストールでも発火する・ネットワーク経由で悪用可能・CVSS 8.8 という3拍子が揃っており、PHP開発者全員が影響対象となる。
幸い、メンテナのJordi Boggiano(Seldaek)は同日に修正版2.2.27/2.9.6をリリース済みだ。更新作業は composer self-update 一行で完了する。CI/CDイメージも合わせて更新し、緊急回避策として --prefer-dist を併用すれば、現実的な攻撃リスクをほぼ封じ込められる。