Gitlab CI/CD に AikidoSec/safe-chain を導入して npm サプライチェーン攻撃対策をしてみた

Gitlab CI/CD に AikidoSec/safe-chain を導入して npm サプライチェーン攻撃対策をしてみた

2025.10.19

はじめに

9月に npm サプライチェーン攻撃「Shai-Hulud」が発生しました。
その際に既知のマルウェア対策として AikidoSec/safe-chain を導入した方も多いのではないでしょうか。

公式には GitHub Actions と Azure DevOps がサポートされていますが、今回は GitLab CI/CD に AikidoSec/safe-chain を導入し、実際に悪意のあるパッケージをブロックできることを確認してみました。

AikidoSec/safe-chain とは

AikidoSec/safe-chain は、悪意のあるパッケージのインストールを防ぐためのセキュリティツールです。
Aikido Security というベルギーに本社を置く会社によって作成され、OSS として GitHub に公開されています。

https://github.com/AikidoSec/safe-chain

仕組み

仕組みとしては npm コマンドを置き換え、npm パッケージのインストール前にインストール対象のパッケージ名とバージョンの組み合わせがマルウェアリストに記載されているかどうかを調べるというものです。

マルウェアリストは以下の URL に JSON ファイルとして設置されています。

https://malware-list.aikido.dev/malware_predictions.json

※ ソースコード内に上記 JSON ファイルを参照する記述があります。

https://github.com/AikidoSec/safe-chain/blob/main/packages/safe-chain/src/api/aikido.js#L4

対象の CI/CD プラットフォームについて

公式には GitHub Actions と Azure DevOps をサポートしていると記載があります。

実際にソースコード上でも環境変数 GITHUB_PATHTF_BUILD が設定されている場合にパスを通すようになっています。

https://github.com/AikidoSec/safe-chain/blob/main/packages/safe-chain/src/shell-integration/setup-ci.js#L108-L122

そこで今回は公式にサポートされていない GitLab CI/CD に AikidoSec/safe-chain を導入してみました。

GitLab CI/CD に AikidoSec/safe-chain を導入してみた

上記で解説した通り、要はパスを通せば動きます。

今回は以下のように、AikidoSec/safe-chain を導入し npm ci を実行するステージを記述した .gitlab-ci.yml を作成しました。

			
			default:
  image: node:latest

stages:
  - setup

setup:
  stage: setup
  script:
    - npm i -g @aikidosec/safe-chain
    - safe-chain setup-ci
    - export PATH="$HOME/.safe-chain/shims:$PATH"
    - npm ci
  artifacts:
    paths:
      - node_modules

		

ブロックすることを確認する

ブロック確認用として配布されている safe-chain-test のインストールを行い、正しくブロックされパイプラインが停止することを確認します。

			
			npm install safe-chain-test

		

package.json は以下の通りです。

			
			{
  "name": "example-safe-chain",
  "version": "1.0.0",
  "dependencies": {
    "safe-chain-test": "^0.0.1-security"
  }
}

		

もしローカルに AikidoSec/safe-chain を導入しており、インストールがブロックされる場合は、以下のように --safe-chain-malware-action=prompt をつけてインストールを行いましょう。

			
			npm install safe-chain-test --safe-chain-malware-action=prompt

		

そうして出力された package-lock.json は以下になります。

			
			{
  "name": "example-safe-chain",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "example-safe-chain",
      "version": "1.0.0",
      "dependencies": {
        "safe-chain-test": "^0.0.1-security"
      }
    },
    "node_modules/safe-chain-test": {
      "version": "0.0.1-security",
      "resolved": "https://registry.npmjs.org/safe-chain-test/-/safe-chain-test-0.0.1-security.tgz",
      "integrity": "sha512-nJoRuRb52IWYNLNX/Bpwot6w+1U1cykpp08eTUdqZOoJ3AcJkiOi4hrHJx4OtT/c4wbK7MoDlKi763DP8BgD2Q=="
    }
  }
}

		

そして gitlab-ci.yml, package.json, package-lock.json の3つをコミット、プッシュし、パイプラインの実行を確認します。

無事失敗を確認できたら成功です。
以下のログに blocked by safe-chain と記述があり、ブロックしてくれたことが確認できました。

			
			$ npm i -g @aikidosec/safe-chain
added 109 packages in 6s
28 packages are looking for funding
  run `npm fund` for details

$ safe-chain setup-ci
Setting up shell aliases. This will wrap safe-chain around npm, npx, yarn, pnpm, pnpx, bun, and bunx commands.
Created 7 Unix shim(s) in /root/.safe-chain/shims
Created shims in /root/.safe-chain/shims
Added shims directory to PATH for CI environments.

$ export PATH="$HOME/.safe-chain/shims:$PATH"

$ npm ci
npm error code E403
npm error 403 403 Forbidden - blocked by safe-chain - GET https://registry.npmjs.org/safe-chain-test/-/safe-chain-test-0.0.1-security.tgz
npm error 403 In most cases, you or one of your dependencies are requesting
npm error 403 a package version that is forbidden by your security policy, or
npm error 403 on a server you do not have access to.
npm error A complete log of this run can be found in: /root/.npm/_logs/2025-10-19T07_11_27_127Z-debug-0.log
Safe-chain: blocked 1 malicious package downloads:
 - safe-chain-test@0.0.1-security (https://registry.npmjs.org/safe-chain-test/-/safe-chain-test-0.0.1-security.tgz)
Exiting without installing malicious packages.
Cleaning up project directory and file based variables
00:00
ERROR: Job failed: exit code 1

		

さいごに

GitLab CI/CD に AikidoSec/safe-chain を導入してみました。

パスを通すというやり方ですので GitLab CI/CD 以外にも CodeBuild や Jenkins などでも同様のやり方で導入することが可能です。

当初はサポートされていなかった bun も 1.1.0 で対応され、主要 npm パッケージマネージャーはすべて対応したので、CI/CD プラットフォームもサポート対象が増えることに期待しています。

この記事をシェアする

FacebookHatena blogX

関連記事