TL;DR
This is the second time a malicious campaign – codenamed Shai‑Hulud – has been detected targeting the npm ecosystem. The first campaign covered in this blog revealed how threat-actors trojanised trusted libraries.
In this current wave:
- Attackers published trojanised versions of trusted packages that execute during install (via a post-install or pre-install hook) to harvest credentials such as developer tokens, CI/CD secrets, and cloud metadata (AWS, GCP, Azure).
- They also established persistence by injecting malicious workflows and connectors: e.g., creating branches named “shai-hulud”, dropping GitHub Actions workflows, uploading stolen data to repositories named “Shai-Hulud”.
- The campaign exhibits worm-like propagation: once a maintainer’s token is compromised, the malware uses it to republish other packages owned by that maintainer – enabling lateral spread across the npm registry.
What happened?
- The campaign abuses compromised maintainer accounts to publish legitimate-looking npm packages. While this builds on earlier activity, the new wave introduces pre-install lifecycle execution of malicious scripts, dramatically raising the risk.
- During installation, payload files (e.g., setup_bun.js, bun_environment.js) are dropped.
- It then registers a self-hosted GitHub Actions runner named “SHA1HULUD” in the compromised repository.
- A workflow .github/workflows/discussion.yaml is added which triggers on GitHub Discussions and executes on the self-hosted runner, enabling arbitrary commands.
- Another workflow .github/workflows/formatter_123456789.yml is pushed which enumerates GitHub secrets, uploads them as an artifact, downloads the artifact, then deletes the branch/workflow to cover tracks.
- The attacker creates files such as cloud.json, contents.json, environment.json, truffleSecrets.json during the install stage, and supports Linux, Windows, and macOS runners.
- Over 25,000 repositories across ~350 unique users were identified as affected. Currently, 26.3k repositories are exposed due to the malware.
- In some bursts ~1,000 new repos were being added every 30 minutes.
- Attacker Errors: A number of packages that were spread via the community contained only the initial staging code (
setup_bun.js) and were missing the main worm (bun_environment.js). This mistake appears to have limited the overall impact of the attack.
Compromised Packages and TTPs
Compromised Packages: A total of 425 compromised packages have been detected with an estimated 132 million monthly downloads. They span major namespaces, including those for Zapier (e.g., @zapier/zapier-sdk (0.15.5–0.15.7), zapier-platform-core (18.0.2–18.0.4)), ENS Domains (@ensdomains/ens-validation 0.1.1), @posthog/agent 1.24.1, and many under @trigo/* and @orbitgtbelgium/*. See appendix for a detailed list.
TTPs Recorded:
| Tactic | Technique ID | Technique Name | Use in This Campaign |
|---|---|---|---|
| Initial Access | T1584 | Compromise Supply Chain: Software Dependency | malicious npm package versions. |
| Execution | T1059.004 | Command and Scripting Interpreter: Unix Shell | pre-install script in package.json. |
| Persistence | T1136 | Create Account | GitHub Actions workflow and self-hosted runner “Shai-Hulud”. |
| Discovery | T1580 | Cloud Infrastructure Discovery | Access to cloud metadata endpoints (AWS/GCP/Azure). |
| Collection | T1005 | Data from Local System | Data files containing encoded secrets (e.g., format.json). |
| Exfiltration | T1041 | Exfiltration Over C2 Channel | Outbound connection to webhook[.]site, creation of GitHub repos named ‘Shai-Hulud’, with new secrets published to repositories using the description “Sha1-Hulud: The Second Coming.” |
Timeline
The initial compromises were detected on 24/11/2025:
- 3:16:26 AM GMT+0: The first packages compromised were go-template and 36 packages from AsyncAPI.
- 4:11:55 AM GMT+0: Compromise of PostHog packages began.
- 5:09:25 AM GMT+0: Compromise of Postman packages began.
What should organisations do?
- Remove and replace compromised packages: Clear npm cache (npm cache clean –force), delete node_modules, rebuild from clean dependencies, and pin to versions prior to November 21, 2025.
- Rotate credentials: Revoke/regenerate npm publishing tokens, GitHub personal access tokens, SSH keys, cloud provider credentials (AWS/GCP/Azure). Enforce phishing-resistant MFA.
- Audit GitHub and CI/CD infrastructure: Search for repositories or branches with names referencing “Shai-Hulud”, review for unauthorized workflows or self-hosted runners, examine recent package publishes in your org.
- Harden pipelines: Disable or limit install-time scripts (preinstall/postinstall) if possible, restrict build-node egress to trusted domains, use least-privilege tokens for automation.
How Orca can help
Orca offers a unified and comprehensive cloud security platform that identifies, prioritizes, and remediates security risks and compliance issues across AWS, Azure, Google Cloud, Oracle Cloud, Alibaba Cloud, and Kubernetes. The Orca Cloud Security Platform leverages Orca’s patented SideScanning™ technology to provide complete coverage and comprehensive risk detection.
Additionally, Orca provides:
- Data Security Posture Management (DSPM): Orca provides DSPM capabilities that helps organizations secure their sensitive data. Orca can help you quickly identify which secrets are present in your environment and where, simplifying and accelerating the process of understanding which secrets were exposed in case of a known attack, and general management of sensitive information day-to-day.
- Inventory: Orca tracks all your cloud assets and identities across your cloud estate, including users, services, and packages. In an attack such as this one, we can help you quickly discover which systems are compromised and help you maintain the incident as fast as possible.
- Exposure management: Even if you accidentally downloaded a malicious npm version, it is not as scary as it could have been if your system does not have any outgoing network permitted. With correct identification of relevant systems you can effectively prioritize how to best detain the situation.
Learn more
Interested in learning more about the Orca Platform? Schedule your personalized 1:1 demo.
Appendix: Full List of Affected Packages
- @accordproject/concerto-analysis
- @accordproject/markdown-docx
- @accordproject/markdown-it-cicero
- @actbase/css-to-react-native-transform
- @actbase/native
- @actbase/node-server
- @actbase/react-absolute
- @actbase/react-daum-postcode
- @actbase/react-kakaosdk
- @actbase/react-native-actionsheet
- @actbase/react-native-devtools
- @actbase/react-native-fast-image
- @actbase/react-native-kakao-channel
- @actbase/react-native-kakao-navi
- @actbase/react-native-less-transformer
- @actbase/react-native-naver-login
- @actbase/react-native-simple-video
- @actbase/react-native-tiktok
- @alexcolls/nuxt-socket.io
- @alexcolls/nuxt-ux
- @aryanhussain/my-angular-lib
- @asyncapi/avro-schema-parser
- @asyncapi/bundler
- @asyncapi/cli
- @asyncapi/converter
- @asyncapi/diff
- @asyncapi/dotnet-rabbitmq-template
- @asyncapi/edavisualiser
- @asyncapi/generator
- @asyncapi/generator-components
- @asyncapi/generator-helpers
- @asyncapi/generator-react-sdk
- @asyncapi/go-watermill-template
- @asyncapi/html-template
- @asyncapi/java-spring-cloud-stream-template
- @asyncapi/java-spring-template
- @asyncapi/java-template
- @asyncapi/keeper
- @asyncapi/markdown-template
- @asyncapi/modelina
- @asyncapi/modelina-cli
- @asyncapi/multi-parser
- @asyncapi/nodejs-template
- @asyncapi/nodejs-ws-template
- @asyncapi/nunjucks-filters
- @asyncapi/openapi-schema-parser
- @asyncapi/optimizer
- @asyncapi/parser
- @asyncapi/php-template
- @asyncapi/problem
- @asyncapi/protobuf-schema-parser
- @asyncapi/python-paho-template
- @asyncapi/react-component
- @asyncapi/server-api
- @asyncapi/specs
- @asyncapi/studio
- @asyncapi/web-component
- @caretive/caret-cli
- @clausehq/flows-step-jsontoxml
- @clausehq/flows-step-sendgridemail
- @commute/bloom
- @commute/market-data
- @dev-blinq/ai-qa-logic
- @dev-blinq/cucumber_client
- @ensdomains/address-encoder
- @ensdomains/blacklist
- @ensdomains/buffer
- @ensdomains/ccip-read-cf-worker
- @ensdomains/ccip-read-dns-gateway
- @ensdomains/ccip-read-router
- @ensdomains/ccip-read-worker-viem
- @ensdomains/content-hash
- @ensdomains/curvearithmetics
- @ensdomains/cypress-metamask
- @ensdomains/dnsprovejs
- @ensdomains/dnssec-oracle-anchors
- @ensdomains/dnssecoraclejs
- @ensdomains/durin
- @ensdomains/durin-middleware
- @ensdomains/ens-archived-contracts
- @ensdomains/ens-avatar
- @ensdomains/ens-contracts
- @ensdomains/ensjs
- @ensdomains/ensjs-react
- @ensdomains/ens-test-env
- @ensdomains/ens-validation
- @ensdomains/eth-ens-namehash
- @ensdomains/hackathon-registrar
- @ensdomains/hardhat-chai-matchers-viem
- @ensdomains/hardhat-toolbox-viem-extended
- @ensdomains/mock
- @ensdomains/name-wrapper
- @ensdomains/offchain-resolver-contracts
- @ensdomains/op-resolver-contracts
- @ensdomains/react-ens-address
- @ensdomains/renewal
- @ensdomains/renewal-widget
- @ensdomains/reverse-records
- @ensdomains/server-analytics
- @ensdomains/solsha1
- @ensdomains/subdomain-registrar
- @ensdomains/test-utils
- @ensdomains/thorin
- @ensdomains/ui
- @ensdomains/unicode-confusables
- @ensdomains/unruggable-gateways
- @ensdomains/vite-plugin-i18next-loader
- @ensdomains/web3modal
- @everreal/web-analytics
- @fishingbooker/browser-sync-plugin
- @fishingbooker/react-swiper
- @hapheus/n8n-nodes-pgp
- @ifelsedeveloper/protocol-contracts-svm-idl
- @ifings/design-system
- @kvytech/cli
- @kvytech/components
- @kvytech/habbit-e2e-test
- @kvytech/medusa-plugin-announcement
- @kvytech/medusa-plugin-management
- @kvytech/medusa-plugin-newsletter
- @kvytech/medusa-plugin-product-reviews
- @kvytech/medusa-plugin-promotion
- @kvytech/web
- @lessondesk/api-client
- @lessondesk/babel-preset
- @lessondesk/eslint-config
- @lessondesk/schoolbus
- @louisle2/core
- @louisle2/cortex-js
- @lpdjs/firestore-repo-service
- @markvivanco/app-version-checker
- @mcp-use/cli
- @mcp-use/inspector
- @mcp-use/mcp-use
- @mparpaillon/connector-parse
- @mparpaillon/imagesloaded
- @orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode
- @orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode
- @orbitgtbelgium/orbit-components
- @orbitgtbelgium/time-slider
- @osmanekrem/error-handler
- @posthog/agent
- @posthog/ai
- @posthog/automatic-cohorts-plugin
- @posthog/bitbucket-release-tracker
- @posthog/cli
- @posthog/clickhouse
- @posthog/core
- @posthog/currency-normalization-plugin
- @posthog/customerio-plugin
- @posthog/databricks-plugin
- @posthog/drop-events-on-property-plugin
- @posthog/event-sequence-timer-plugin
- @posthog/filter-out-plugin
- @posthog/first-time-event-tracker
- @posthog/geoip-plugin
- @posthog/github-release-tracking-plugin
- @posthog/gitub-star-sync-plugin
- @posthog/heartbeat-plugin
- @posthog/hedgehog-mode
- @posthog/icons
- @posthog/ingestion-alert-plugin
- @posthog/intercom-plugin
- @posthog/kinesis-plugin
- @posthog/laudspeaker-plugin
- @posthog/lemon-ui
- @posthog/maxmind-plugin
- @posthog/migrator3000-plugin
- @posthog/netdata-event-processing
- @posthog/nextjs
- @posthog/nextjs-config
- @posthog/nuxt
- @posthog/pagerduty-plugin
- @posthog/piscina
- @posthog/plugin-contrib
- @posthog/plugin-server
- @posthog/plugin-unduplicates
- @posthog/postgres-plugin
- @posthog/react-rrweb-player
- @posthog/rrdom
- @posthog/rrweb
- @posthog/rrweb-player
- @posthog/rrweb-record
- @posthog/rrweb-replay
- @posthog/rrweb-snapshot
- @posthog/rrweb-utils
- @posthog/sendgrid-plugin
- @posthog/siphash
- @posthog/snowflake-export-plugin
- @posthog/taxonomy-plugin
- @posthog/twilio-plugin
- @posthog/twitter-followers-plugin
- @posthog/url-normalizer-plugin
- @posthog/variance-plugin
- @posthog/web-dev-server
- @posthog/wizard
- @posthog/zendesk-plugin
- @postman/aether-icons
- @postman/csv-parse
- @postman/final-node-keytar
- @postman/mcp-ui-client
- @postman/node-keytar
- @postman/pm-bin-linux-x64
- @postman/pm-bin-macos-arm64
- @postman/pm-bin-macos-x64
- @postman/pm-bin-windows-x64
- @postman/postman-collection-fork
- @postman/postman-mcp-cli
- @postman/postman-mcp-server
- @postman/pretty-ms
- @postman/secret-scanner-wasm
- @postman/tunnel-agent
- @postman/wdio-allure-reporter
- @postman/wdio-junit-reporter
- @quick-start-soft/quick-document-translator
- @quick-start-soft/quick-git-clean-markdown
- @quick-start-soft/quick-markdown
- @quick-start-soft/quick-markdown-compose
- @quick-start-soft/quick-markdown-image
- @quick-start-soft/quick-markdown-print
- @quick-start-soft/quick-markdown-translator
- @quick-start-soft/quick-remove-image-background
- @quick-start-soft/quick-task-refine
- @seung-ju/next
- @seung-ju/openapi-generator
- @seung-ju/react-hooks
- @seung-ju/react-native-action-sheet
- @strapbuild/react-native-date-time-picker
- @strapbuild/react-native-perspective-image-cropper
- @strapbuild/react-native-perspective-image-cropper-2
- @strapbuild/react-native-perspective-image-cropper-poojan31
- @thedelta/eslint-config
- @tiaanduplessis/json
- @tiaanduplessis/react-progressbar
- @trefox/sleekshop-js
- @trigo/atrix
- @trigo/atrix-acl
- @trigo/atrix-elasticsearch
- @trigo/atrix-mongoose
- @trigo/atrix-orientdb
- @trigo/atrix-postgres
- @trigo/atrix-pubsub
- @trigo/atrix-redis
- @trigo/atrix-soap
- @trigo/atrix-swagger
- @trigo/bool-expressions
- @trigo/eslint-config-trigo
- @trigo/fsm
- @trigo/hapi-auth-signedlink
- @trigo/jsdt
- @trigo/keycloak-api
- @trigo/node-soap
- @trigo/pathfinder-ui-css
- @trigo/trigo-hapijs
- @varsityvibe/api-client
- @varsityvibe/validation-schemas
- @zapier/ai-actions
- @zapier/ai-actions-react
- @zapier/babel-preset-zapier
- @zapier/browserslist-config-zapier
- @zapier/eslint-plugin-zapier
- @zapier/mcp-integration
- @zapier/secret-scrubber
- @zapier/spectral-api-ruleset
- @zapier/stubtree
- @zapier/zapier-sdk
- asyncapi-preview
- atrix
- atrix-mongoose
- axios-builder
- axios-cancelable
- axios-timed
- barebones-css
- blinqio-executions-cli
- bool-expressions
- bun-plugin-httpfile
- bytecode-checker-cli
- bytes-to-x
- calc-loan-interest
- capacitor-plugin-apptrackingios
- capacitor-plugin-purchase
- capacitor-plugin-scgssigninwithgoogle
- capacitor-purchase-history
- capacitor-voice-recorder-wav
- chrome-extension-downloads
- claude-token-updater
- coinmarketcap-api
- command-irail
- compare-obj
- count-it-down
- cpu-instructions
- create-glee-app
- create-hardhat3-app
- create-mcp-use-app
- crypto-addr-codec
- designstudiouiux
- devstart-cli
- discord-bot-server
- dotnet-template
- drop-events-on-property-plugin
- enforce-branch-name
- eslint-config-trigo
- eslint-config-zeallat-base
- ethereum-ens
- evm-checkcode-cli
- exact-ticker
- expo-audio-session
- feature-flip
- fittxt
- flapstacks
- flatten-unflatten
- formik-error-focus
- formik-store
- fuzzy-finder
- gate-evm-check-code2
- gate-evm-tools-test
- gatsby-plugin-cname
- get-them-args
- github-action-for-generator
- gitsafe
- go-template
- haufe-axera-api-client
- hopedraw
- hope-mapboxdraw
- hyperterm-hipster
- image-to-uri
- invo
- iron-shield-miniapp
- ito-button
- itobuz-angular
- itobuz-angular-auth
- jacob-zuma
- jan-browser
- jquery-bindings
- just-toasty
- kill-port
- korea-administrative-area-geo-json-util
- license-o-matic
- lint-staged-imagemin
- lite-serper-mcp-server
- luno-api
- manual-billing-system-miniapp-api
- mcp-use
- medusa-plugin-announcement
- medusa-plugin-logs
- medusa-plugin-momo
- medusa-plugin-product-reviews-kvy
- medusa-plugin-zalopay
- mon-package-react-typescript
- n8n-nodes-tmdb
- nanoreset
- next-circular-dependency
- obj-to-css
- okta-react-router-6
- open2internet
- orbit-boxicons
- orbit-nebula-draw-tools
- orbit-nebula-editor
- orbit-soap
- parcel-plugin-asset-copier
- piclite
- pico-uid
- poper-react-sdk
- posthog-docusaurus
- posthog-js
- posthog-node
- posthog-plugin-hello-world
- posthog-react-native
- posthog-react-native-session-replay
- ra-data-firebase
- react-component-taggers
- react-element-prompt-inspector
- react-jam-icons
- react-keycloak-context
- react-library-setup
- react-native-datepicker-modal
- react-native-email
- react-native-fetch
- react-native-get-pixel-dimensions
- react-native-jam-icons
- react-native-log-level
- react-native-phone-call
- react-native-retriable-fetch
- react-native-use-modal
- react-native-view-finder
- react-native-websocket
- react-native-worklet-functions
- react-qr-image
- redux-forge
- redux-router-kit
- sa-company-registration-number-regex
- sa-id-gen
- scgs-capacitor-subscribe
- scgsffcreator
- set-nested-prop
- shell-exec
- shinhan-limit-scrap
- skills-use
- sort-by-distance
- stoor
- svelte-autocomplete-select
- tcsp-draw-test
- tenacious-fetch
- test23112222-api
- test-foundry-app
- test-hardhat-app
- token.js-fork
- trigo-react-app
- typeorm-orbit
- undefsafe-typed
- uplandui
- url-encode-decode
- vite-plugin-httpfile
- web-types-htmx
- web-types-lit
- wenk
- zapier-async-storage
- zapier-platform-cli
- zapier-platform-core
- zapier-platform-legacy-scripting-runner
- zapier-platform-schema
- zapier-scripts
- zuper-cli
- zuper-sdk
- zuper-stream
