[Shai-Hulud対策] safe-chainをGitlab CIパイプラインに導入する
Shai-Huludとは
9月15日にNPMパッケージへのサプライチェーン攻撃が観測され、「Shai-Hulud攻撃」と名付けられました。
本攻撃は自己増殖性という性質をもち、一度インストールすると他のパッケージまで汚染してしまうというやばいやつです。
もし汚染されたパッケージをインストールしてしまうと、インストール環境に勝手にバックドアが作られ認証情報やCredential情報が攻撃元に送信されてしまうという多大なリスクがあります。
私が関わるプロジェクトでは当時該当とされるパッケージやライブラリの利用は確認されませんでしたが、自己増殖性という性質をもつため今後汚染パッケージは増大されると予測されており注意が必要です。
詳細は以下をご参照ください:
対策
今対応パッケージを使用していないから安心というわけではなく、今後汚染パッケージをインストールしないことが重要です。
そこで今回 safe-chain というツールを導入することにしました。
npm cli、npx、yarn、pnpm、pnpxをラップし、新しいパッケージをインストールする前に追加のチェックを提供します。このツールは、パッケージにマルウェアが含まれていることを検出し、終了を促すプロンプトを表示することで、npm、npx、yarn、pnpm、pnpxによるマルウェアのダウンロードや実行を防止します。
公式より引用
Gitlab CIに組み込む
safe-chainのREADMEにCIを有効化する手順が記載されていますが、GitLabがなかったため作成してみました。
stages:
- security
variables:
SAFE_CHAIN_TARGET: "package.json"
SAFE_CHAIN_LOCK: "package-lock.json"
# 攻撃が確認された日付
SAFE_CHAIN_DATE_THRESHOLD: "2025-09-15"
GIT_DEPTH: "0"
safe_chain_check:
stage: security
image: node:20
tags:
- docker # Runner
before_script:
- apt-get update -y && apt-get install -y git
- npm install -g @aikidosec/safe-chain
- safe-chain setup-ci --shell sh
- export PATH="$HOME/.safe-chain/shims:$PATH"
- command -v npm
script:
- |
set -euo pipefail
npm_version="$(npm -v)"
echo "Detected npm version: ${npm_version}"
# npmのバージョン比較: $1 >= $2 なら真
version_ge() {
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | tail -n1)" = "$1" ]
}
run_safe_chain() {
echo "Running safe-chain on: ${SAFE_CHAIN_TARGET}"
target_dir="$(dirname "${SAFE_CHAIN_TARGET}")"
(
cd "${target_dir}"
npm install
)
echo "✅ safe-chain completed successfully"
}
# 分岐ロジック
# Npmが10.4.0以上であること、package.json関連が2025-09-15以降である場合に検証を実施
if version_ge "$npm_version" "10.4.0"; then
echo "npm >= 10.4.0 → ${SAFE_CHAIN_TARGET} を検査"
run_safe_chain
else
echo "npm < 10.4.0 → ${SAFE_CHAIN_DATE_THRESHOLD} 以降に ${SAFE_CHAIN_LOCK} が更新されているか確認"
if [ -f "$SAFE_CHAIN_LOCK" ] && git log --since="$SAFE_CHAIN_DATE_THRESHOLD" --format=%H -- "$SAFE_CHAIN_LOCK" | grep -q .; then
echo "ロックファイルが閾値日付以降に更新 → 検査実行"
run_safe_chain
else
echo "条件不成立 → Safe-chain をスキップ"
fi
fi
検証
テスト用に、npm install safe-chain-test
パッケージがブロック対象となっているとのことで、以下を挿入しテストをしてみます。
(
cd "${target_dir}"
npm install
npm install --no-save safe-chain-test
)
無事パイプラインの失敗が確認できました。
safe-chain-testを削除すると成功することが確認できました。
おわりに
本攻撃のリスクは高く、自己増殖性という観点から完璧な対策は難しいと思われます。
今後の動向に十分注意していきましょう!
Discussion