🐈

[Shai-Hulud対策] safe-chainをGitlab CIパイプラインに導入する

に公開

Shai-Huludとは

9月15日にNPMパッケージへのサプライチェーン攻撃が観測され、「Shai-Hulud攻撃」と名付けられました。
本攻撃は自己増殖性という性質をもち、一度インストールすると他のパッケージまで汚染してしまうというやばいやつです。

もし汚染されたパッケージをインストールしてしまうと、インストール環境に勝手にバックドアが作られ認証情報やCredential情報が攻撃元に送信されてしまうという多大なリスクがあります。

私が関わるプロジェクトでは当時該当とされるパッケージやライブラリの利用は確認されませんでしたが、自己増殖性という性質をもつため今後汚染パッケージは増大されると予測されており注意が必要です。

詳細は以下をご参照ください:
https://gigazine.net/news/20250917-shai-hulud-npm-packages/

対策

今対応パッケージを使用していないから安心というわけではなく、今後汚染パッケージをインストールしないことが重要です。
そこで今回 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を削除すると成功することが確認できました。

おわりに

本攻撃のリスクは高く、自己増殖性という観点から完璧な対策は難しいと思われます。
今後の動向に十分注意していきましょう!

BLT SDC Tech Blog

Discussion