TL;DR for engineering teams
- Another supply chain and npm maintainer were compromised after the QIX compromise.
- The campaign, named Shai-Hulud, continues to target TinyColor and now CrowdStrike npm packages.
- Another account, following the pattern campaign on npm, has been compromised.
- The malware is identical to the tinycolor malware, which includes a
bundle.js
script that:- Downloads and executes TruffleHog, a legitimate secret scanner
- Searches host systems for tokens and cloud credentials
- Validates discovered developer and CI credentials
- Creates unauthorized GitHub Actions workflows within repositories
- Exfiltrates sensitive data to a hardcoded webhook endpoint
- Do not install @ctrl/tinycolor@4.1.1 or @4.1.2 (and avoid any dependency graph that resolves to them). The same campaign hit 40-74+ other packages (full list below).
- The malware uses a self-propagating function (NpmModule.updatePackage) to grab maintainer packages, inject a Webpack-bundled bundle.js, repack, and republish—creating a blast radius across maintainers and dependents.
- The payload pulls down TruffleHog, hunts for GITHUB_TOKEN, NPM_TOKEN, AWS/GCP/Azure credentials, validates tokens (npm whoami), hits GitHub APIs, writes a persistence GitHub Actions workflow that exfiltrates secrets to webhook[.]site, and can persist in CI even after the original host is clean. IoCs and exfil link below.
- Initial alert attribution includes Daniel dos Santos Pereira and community triage; Socket and StepSecurity published detailed breakdowns and IoCs.
- Rotate tokens, rip out the backdoor workflow, scan repos/org for Shai-Hulud branch and workflow, audit your clouds’ secret access, and lock down publish paths. Guidance and commands included.
- Thanks to Daniel Pereira for the initial alert:
Update 19 September
- New Indicator of Compromise 23 New libraries affected, bringing the total to 526 libraries,
- Script updated to include detection
Update 18 September
- New Indicator of Compromise 27 New libraries affected, bringing the total to 504 libraries,
- Script updated, plus integration with Phoenix
Update 17 September
- The number of libraries affected has increased from 40-74 to 477+
What was compromised, and how it spread
This was not a one-off malicious post-install. It’s a small supply-chain engine:
- Trojanization pipeline
The attacker’s code downloads a package tarball, modifies package.json, injects a local bundle.js, repacks, and republishes. That updatePackage function automates the spread across a maintainer’s other packages, weaponizing maintainer trust at scale. - Execution vector
The minified bundle.js (≈3.6MB) runs during install. It fingerprints the OS, pulls a matching TruffleHog binary, and starts secret harvesting. The code validates npm auth via /-/whoami, calls GitHub REST if a token is present, and probes cloud metadata endpoints used by build agents. - Persistence and exfiltration
If GitHub access is available, the script writes a workflow at .github/workflows/shai-hulud-workflow.yml. That workflow serializes secrets and posts to a webhook[.]site endpoint. Once committed, secrets can leak from future CI runs even if the developer’s laptop is clean. IoC hash and exfil URL are fixed. - Scope and blast radius
@ctrl/tinycolor counted ~2M weekly downloads and is just one node in the set. The same campaign hit multiple maintainers and org scopes, including CrowdStrike-scoped packages and a swath of @ctrl/* modules.
How to verify packages:
Launch our quick check tool:
python3 npm_compromise_detector.py ‘/path/to/your/project’ –output security-audit.txt –check-cache –full-tree –show-locations
How to Check if You Are Affected by Shaia Hulud and verify in Phoenix Security:
If you are a Phoenix Security client, verify your SBOM dependencies from 3rd party of from Phoenix Security Scanner:
- SBOM Screen: Verify the main packages
- https://YOURDOMAIN/app/external-dependencies/libraries?q=eJyrrgUAAXUA%2BQ%3D%3D
How to remediate / Prevention measures against Shaia Hulud NPM campaigns and follow-up
Attack surface is expanding, and developers distributed across an organization is the worst recipe for NPM attacks like this. Following a list of steps to consider to prevent this attack from spreading
Key suggestions
- Pin Dependencies. Avoid auto update, pin dependencies
- Prevent direct access/ update from NPM or other package managers (see below)
- Prevent unvetted updates using a proxy
To respond and be prepared to Shaia Hulud and other NPM source package attacks, follow the quick recommendation. For detailed guidelines, check npm-shai-hulud-supply-chain-compromise-explained
To defend against npm supply chain attacks and recover fast when incidents strike, adopt these practices:
- Lock & Pin Dependencies – Use package-lock.json/pnpm-lock.yaml with npm ci (not npm install) and set save-exact=true in .npmrc.
- Proxy & Sanitize – Route all installs through an internal package manager proxy (e.g., Nexus/Artifactory) that caches and sanitizes approved versions.
- Restrict Registry Access – Temporarily block direct access to npm when an active campaign is underway, forcing developers to pull only vetted packages.
- Detect & Monitor – Integrate SCA + malware scanning in CI/CD to catch compromised dependencies early, with reachability analysis to reduce noise.
- Delay Adoption – Apply a “cooldown period” (e.g., 60 days for new packages) before trusting fresh releases.
- Reduce Bloat – Eliminate unused or duplicate libraries, and leverage reachability analysis to prune non-critical dependencies.
- Recovery Playbook: Responding to a Compromise
- Isolate & Identify: Freeze deployments and check lockfiles against compromised versions.
- Eradicate & Clean: Remove malicious packages, update to safe versions, purge caches, and commit fresh lockfiles.
- Rotate All Credentials: Reset every token and secret used in CI/CD (GitHub, npm, cloud keys).
- Audit for Persistence: Hunt for backdoors (e.g., malicious workflows) and remove them before resuming operations.
Packages confirmed in this campaign
Do not install @ctrl/tinycolor@4.1.1+ (or any resolver path that selects those versions) until you’ve verified provenance. The maintainer account scttcper is the publisher for many of the affected @ctrl/* and Angular packages; treat any recent publishes with extreme caution while provenance is established.
Refer to the full analysis of Shaia Hulud for full analysis and details on the waves.
Full Path | Root | Library | Version | NEW FINDING |
@ahmedhfarag/ngx-perfect-scrollbar@20.0.20 | @ahmedhfarag | ngx-perfect-scrollbar | 20.0.20 | PREVIOUS REPORT |
@ahmedhfarag/ngx-virtual-scroller@4.0.4 | @ahmedhfarag | ngx-virtual-scroller | 4.0.4 | PREVIOUS REPORT |
@art-ws/common@2.0.28 | @art-ws | common | 2.0.28 | PREVIOUS REPORT |
@art-ws/config-eslint@2.0.4 | @art-ws | config-eslint | 2.0.4 | PREVIOUS REPORT |
@art-ws/config-eslint@2.0.5 | @art-ws | config-eslint | 2.0.5 | PREVIOUS REPORT |
@art-ws/config-ts@2.0.7 | @art-ws | config-ts | 2.0.7 | PREVIOUS REPORT |
@art-ws/config-ts@2.0.8 | @art-ws | config-ts | 2.0.8 | PREVIOUS REPORT |
@art-ws/db-context@2.0.24 | @art-ws | db-context | 2.0.24 | PREVIOUS REPORT |
@art-ws/di-node@2.0.13 | @art-ws | di-node | 2.0.13 | PREVIOUS REPORT |
@art-ws/di@2.0.28 | @art-ws | di | 2.0.28 | PREVIOUS REPORT |
@art-ws/di@2.0.32 | @art-ws | di | 2.0.32 | PREVIOUS REPORT |
@art-ws/eslint@1.0.5 | @art-ws | eslint | 1.0.5 | PREVIOUS REPORT |
@art-ws/eslint@1.0.6 | @art-ws | eslint | 1.0.6 | PREVIOUS REPORT |
@art-ws/fastify-http-server@2.0.24 | @art-ws | fastify-http-server | 2.0.24 | PREVIOUS REPORT |
@art-ws/fastify-http-server@2.0.27 | @art-ws | fastify-http-server | 2.0.27 | PREVIOUS REPORT |
@art-ws/http-server@2.0.21 | @art-ws | http-server | 2.0.21 | PREVIOUS REPORT |
@art-ws/http-server@2.0.25 | @art-ws | http-server | 2.0.25 | PREVIOUS REPORT |
@art-ws/openapi@0.1.12 | @art-ws | openapi | 0.1.12 | PREVIOUS REPORT |
@art-ws/openapi@0.1.9 | @art-ws | openapi | 0.1.9 | PREVIOUS REPORT |
@art-ws/package-base@1.0.5 | @art-ws | package-base | 1.0.5 | PREVIOUS REPORT |
@art-ws/package-base@1.0.6 | @art-ws | package-base | 1.0.6 | PREVIOUS REPORT |
@art-ws/prettier@1.0.5 | @art-ws | prettier | 1.0.5 | PREVIOUS REPORT |
@art-ws/prettier@1.0.6 | @art-ws | prettier | 1.0.6 | PREVIOUS REPORT |
@art-ws/slf@2.0.15 | @art-ws | slf | 2.0.15 | PREVIOUS REPORT |
@art-ws/slf@2.0.22 | @art-ws | slf | 2.0.22 | PREVIOUS REPORT |
@art-ws/ssl-info@1.0.10 | @art-ws | ssl-info | 1.0.10 | PREVIOUS REPORT |
@art-ws/ssl-info@1.0.9 | @art-ws | ssl-info | 1.0.9 | PREVIOUS REPORT |
@art-ws/web-app@1.0.3 | @art-ws | web-app | 1.0.3 | PREVIOUS REPORT |
@art-ws/web-app@1.0.4 | @art-ws | web-app | 1.0.4 | PREVIOUS REPORT |
@crowdstrike/commitlint@8.1.1 | @crowdstrike | commitlint | 8.1.1 | PREVIOUS REPORT |
@crowdstrike/commitlint@8.1.2 | @crowdstrike | commitlint | 8.1.2 | PREVIOUS REPORT |
@crowdstrike/falcon-shoelace@0.4.1 | @crowdstrike | falcon-shoelace | 0.4.1 | PREVIOUS REPORT |
@crowdstrike/falcon-shoelace@0.4.2 | @crowdstrike | falcon-shoelace | 0.4.2 | PREVIOUS REPORT |
@crowdstrike/foundry-js@0.19.1 | @crowdstrike | foundry-js | 0.19.1 | PREVIOUS REPORT |
@crowdstrike/foundry-js@0.19.2 | @crowdstrike | foundry-js | 0.19.2 | PREVIOUS REPORT |
@crowdstrike/glide-core@0.34.2 | @crowdstrike | glide-core | 0.34.2 | PREVIOUS REPORT |
@crowdstrike/glide-core@0.34.3 | @crowdstrike | glide-core | 0.34.3 | PREVIOUS REPORT |
@crowdstrike/logscale-dashboard@1.205.1 | @crowdstrike | logscale-dashboard | 1.205.1 | PREVIOUS REPORT |
@crowdstrike/logscale-dashboard@1.205.2 | @crowdstrike | logscale-dashboard | 1.205.2 | PREVIOUS REPORT |
@crowdstrike/logscale-file-editor@1.205.1 | @crowdstrike | logscale-file-editor | 1.205.1 | PREVIOUS REPORT |
@crowdstrike/logscale-file-editor@1.205.2 | @crowdstrike | logscale-file-editor | 1.205.2 | PREVIOUS REPORT |
@crowdstrike/logscale-parser-edit@1.205.1 | @crowdstrike | logscale-parser-edit | 1.205.1 | PREVIOUS REPORT |
@crowdstrike/logscale-parser-edit@1.205.2 | @crowdstrike | logscale-parser-edit | 1.205.2 | PREVIOUS REPORT |
@crowdstrike/logscale-search@1.205.1 | @crowdstrike | logscale-search | 1.205.1 | PREVIOUS REPORT |
@crowdstrike/logscale-search@1.205.2 | @crowdstrike | logscale-search | 1.205.2 | PREVIOUS REPORT |
@crowdstrike/tailwind-toucan-base@5.0.1 | @crowdstrike | tailwind-toucan-base | 5.0.1 | PREVIOUS REPORT |
@crowdstrike/tailwind-toucan-base@5.0.2 | @crowdstrike | tailwind-toucan-base | 5.0.2 | PREVIOUS REPORT |
@ctrl/deluge@7.2.1 | @ctrl | deluge | 7.2.1 | PREVIOUS REPORT |
@ctrl/deluge@7.2.2 | @ctrl | deluge | 7.2.2 | PREVIOUS REPORT |
@ctrl/golang-template@1.4.2 | @ctrl | golang-template | 1.4.2 | PREVIOUS REPORT |
@ctrl/golang-template@1.4.3 | @ctrl | golang-template | 1.4.3 | PREVIOUS REPORT |
@ctrl/magnet-link@4.0.3 | @ctrl | magnet-link | 4.0.3 | PREVIOUS REPORT |
@ctrl/magnet-link@4.0.4 | @ctrl | magnet-link | 4.0.4 | PREVIOUS REPORT |
@ctrl/ngx-codemirror@7.0.1 | @ctrl | ngx-codemirror | 7.0.1 | PREVIOUS REPORT |
@ctrl/ngx-codemirror@7.0.2 | @ctrl | ngx-codemirror | 7.0.2 | PREVIOUS REPORT |
@ctrl/ngx-csv@6.0.1 | @ctrl | ngx-csv | 6.0.1 | PREVIOUS REPORT |
@ctrl/ngx-csv@6.0.2 | @ctrl | ngx-csv | 6.0.2 | PREVIOUS REPORT |
@ctrl/ngx-emoji-mart@9.2.1 | @ctrl | ngx-emoji-mart | 9.2.1 | PREVIOUS REPORT |
@ctrl/ngx-emoji-mart@9.2.2 | @ctrl | ngx-emoji-mart | 9.2.2 | PREVIOUS REPORT |
@ctrl/ngx-rightclick@4.0.1 | @ctrl | ngx-rightclick | 4.0.1 | PREVIOUS REPORT |
@ctrl/ngx-rightclick@4.0.2 | @ctrl | ngx-rightclick | 4.0.2 | PREVIOUS REPORT |
@ctrl/qbittorrent@9.7.1 | @ctrl | qbittorrent | 9.7.1 | PREVIOUS REPORT |
@ctrl/qbittorrent@9.7.2 | @ctrl | qbittorrent | 9.7.2 | PREVIOUS REPORT |
@ctrl/react-adsense@2.0.1 | @ctrl | react-adsense | 2.0.1 | PREVIOUS REPORT |
@ctrl/react-adsense@2.0.2 | @ctrl | react-adsense | 2.0.2 | PREVIOUS REPORT |
@ctrl/shared-torrent@6.3.1 | @ctrl | shared-torrent | 6.3.1 | PREVIOUS REPORT |
@ctrl/shared-torrent@6.3.2 | @ctrl | shared-torrent | 6.3.2 | PREVIOUS REPORT |
@ctrl/tinycolor@4.1.1 | @ctrl | tinycolor | 4.1.1 | PREVIOUS REPORT |
@ctrl/tinycolor@4.1.2 | @ctrl | tinycolor | 4.1.2 | PREVIOUS REPORT |
@ctrl/torrent-file@4.1.1 | @ctrl | torrent-file | 4.1.1 | PREVIOUS REPORT |
@ctrl/torrent-file@4.1.2 | @ctrl | torrent-file | 4.1.2 | PREVIOUS REPORT |
@ctrl/transmission@7.3.1 | @ctrl | transmission | 7.3.1 | PREVIOUS REPORT |
@ctrl/ts-base32@4.0.1 | @ctrl | ts-base32 | 4.0.1 | PREVIOUS REPORT |
@ctrl/ts-base32@4.0.2 | @ctrl | ts-base32 | 4.0.2 | PREVIOUS REPORT |
@hestjs/core@0.2.1 | @hestjs | core | 0.2.1 | PREVIOUS REPORT |
@hestjs/cqrs@0.1.6 | @hestjs | cqrs | 0.1.6 | PREVIOUS REPORT |
@hestjs/demo@0.1.2 | @hestjs | demo | 0.1.2 | PREVIOUS REPORT |
@hestjs/eslint-config@0.1.2 | @hestjs | eslint-config | 0.1.2 | PREVIOUS REPORT |
@hestjs/logger@0.1.6 | @hestjs | logger | 0.1.6 | PREVIOUS REPORT |
@hestjs/scalar@0.1.7 | @hestjs | scalar | 0.1.7 | PREVIOUS REPORT |
@hestjs/validation@0.1.6 | @hestjs | validation | 0.1.6 | PREVIOUS REPORT |
@nativescript-community/arraybuffers@1.1.6 | @nativescript-community | arraybuffers | 1.1.6 | PREVIOUS REPORT |
@nativescript-community/arraybuffers@1.1.7 | @nativescript-community | arraybuffers | 1.1.7 | PREVIOUS REPORT |
@nativescript-community/arraybuffers@1.1.8 | @nativescript-community | arraybuffers | 1.1.8 | PREVIOUS REPORT |
@nativescript-community/gesturehandler@2.0.35 | @nativescript-community | gesturehandler | 2.0.35 | PREVIOUS REPORT |
@nativescript-community/perms@3.0.5 | @nativescript-community | perms | 3.0.5 | PREVIOUS REPORT |
@nativescript-community/perms@3.0.6 | @nativescript-community | perms | 3.0.6 | PREVIOUS REPORT |
@nativescript-community/perms@3.0.7 | @nativescript-community | perms | 3.0.7 | PREVIOUS REPORT |
@nativescript-community/perms@3.0.8 | @nativescript-community | perms | 3.0.8 | PREVIOUS REPORT |
@nativescript-community/perms@3.0.9 | @nativescript-community | perms | 3.0.9 | NEW FINDING |
@nativescript-community/sentry@4.6.43 | @nativescript-community | sentry | 4.6.43 | PREVIOUS REPORT |
@nativescript-community/sqlite@3.5.2 | @nativescript-community | sqlite | 3.5.2 | PREVIOUS REPORT |
@nativescript-community/sqlite@3.5.3 | @nativescript-community | sqlite | 3.5.3 | PREVIOUS REPORT |
@nativescript-community/sqlite@3.5.4 | @nativescript-community | sqlite | 3.5.4 | PREVIOUS REPORT |
@nativescript-community/sqlite@3.5.5 | @nativescript-community | sqlite | 3.5.5 | PREVIOUS REPORT |
@nativescript-community/text@1.6.10 | @nativescript-community | text | 1.6.10 | PREVIOUS REPORT |
@nativescript-community/text@1.6.11 | @nativescript-community | text | 1.6.11 | PREVIOUS REPORT |
@nativescript-community/text@1.6.12 | @nativescript-community | text | 1.6.12 | PREVIOUS REPORT |
@nativescript-community/text@1.6.13 | @nativescript-community | text | 1.6.13 | PREVIOUS REPORT |
@nativescript-community/text@1.6.9 | @nativescript-community | text | 1.6.9 | PREVIOUS REPORT |
@nativescript-community/typeorm@0.2.30 | @nativescript-community | typeorm | 0.2.30 | PREVIOUS REPORT |
@nativescript-community/typeorm@0.2.31 | @nativescript-community | typeorm | 0.2.31 | PREVIOUS REPORT |
@nativescript-community/typeorm@0.2.32 | @nativescript-community | typeorm | 0.2.32 | PREVIOUS REPORT |
@nativescript-community/typeorm@0.2.33 | @nativescript-community | typeorm | 0.2.33 | PREVIOUS REPORT |
@nativescript-community/ui-collectionview@6.0.6 | @nativescript-community | ui-collectionview | 6.0.6 | PREVIOUS REPORT |
@nativescript-community/ui-document-picker@1.1.27 | @nativescript-community | ui-document-picker | 1.1.27 | PREVIOUS REPORT |
@nativescript-community/ui-document-picker@1.1.28 | @nativescript-community | ui-document-picker | 1.1.28 | PREVIOUS REPORT |
@nativescript-community/ui-drawer@0.1.30 | @nativescript-community | ui-drawer | 0.1.30 | PREVIOUS REPORT |
@nativescript-community/ui-image@4.5.6 | @nativescript-community | ui-image | 4.5.6 | PREVIOUS REPORT |
@nativescript-community/ui-label@1.3.35 | @nativescript-community | ui-label | 1.3.35 | PREVIOUS REPORT |
@nativescript-community/ui-label@1.3.36 | @nativescript-community | ui-label | 1.3.36 | PREVIOUS REPORT |
@nativescript-community/ui-label@1.3.37 | @nativescript-community | ui-label | 1.3.37 | PREVIOUS REPORT |
@nativescript-community/ui-material-bottom-navigation@7.2.72 | @nativescript-community | ui-material-bottom-navigation | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-bottom-navigation@7.2.73 | @nativescript-community | ui-material-bottom-navigation | 7.2.73 | PREVIOUS REPORT |
@nativescript-community/ui-material-bottom-navigation@7.2.74 | @nativescript-community | ui-material-bottom-navigation | 7.2.74 | PREVIOUS REPORT |
@nativescript-community/ui-material-bottom-navigation@7.2.75 | @nativescript-community | ui-material-bottom-navigation | 7.2.75 | PREVIOUS REPORT |
@nativescript-community/ui-material-bottomsheet@7.2.72 | @nativescript-community | ui-material-bottomsheet | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-core-tabs@7.2.72 | @nativescript-community | ui-material-core-tabs | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-core-tabs@7.2.73 | @nativescript-community | ui-material-core-tabs | 7.2.73 | PREVIOUS REPORT |
@nativescript-community/ui-material-core-tabs@7.2.74 | @nativescript-community | ui-material-core-tabs | 7.2.74 | PREVIOUS REPORT |
@nativescript-community/ui-material-core-tabs@7.2.75 | @nativescript-community | ui-material-core-tabs | 7.2.75 | PREVIOUS REPORT |
@nativescript-community/ui-material-core-tabs@7.2.76 | @nativescript-community | ui-material-core-tabs | 7.2.76 | PREVIOUS REPORT |
@nativescript-community/ui-material-core@7.2.72 | @nativescript-community | ui-material-core | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-core@7.2.73 | @nativescript-community | ui-material-core | 7.2.73 | PREVIOUS REPORT |
@nativescript-community/ui-material-core@7.2.74 | @nativescript-community | ui-material-core | 7.2.74 | PREVIOUS REPORT |
@nativescript-community/ui-material-core@7.2.75 | @nativescript-community | ui-material-core | 7.2.75 | PREVIOUS REPORT |
@nativescript-community/ui-material-core@7.2.76 | @nativescript-community | ui-material-core | 7.2.76 | PREVIOUS REPORT |
@nativescript-community/ui-material-ripple@7.2.72 | @nativescript-community | ui-material-ripple | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-ripple@7.2.73 | @nativescript-community | ui-material-ripple | 7.2.73 | PREVIOUS REPORT |
@nativescript-community/ui-material-ripple@7.2.74 | @nativescript-community | ui-material-ripple | 7.2.74 | PREVIOUS REPORT |
@nativescript-community/ui-material-ripple@7.2.75 | @nativescript-community | ui-material-ripple | 7.2.75 | PREVIOUS REPORT |
@nativescript-community/ui-material-tabs@7.2.72 | @nativescript-community | ui-material-tabs | 7.2.72 | PREVIOUS REPORT |
@nativescript-community/ui-material-tabs@7.2.73 | @nativescript-community | ui-material-tabs | 7.2.73 | PREVIOUS REPORT |
@nativescript-community/ui-material-tabs@7.2.74 | @nativescript-community | ui-material-tabs | 7.2.74 | PREVIOUS REPORT |
@nativescript-community/ui-material-tabs@7.2.75 | @nativescript-community | ui-material-tabs | 7.2.75 | PREVIOUS REPORT |
@nativescript-community/ui-pager@14.1.36 | @nativescript-community | ui-pager | 14.1.36 | PREVIOUS REPORT |
@nativescript-community/ui-pager@14.1.37 | @nativescript-community | ui-pager | 14.1.37 | PREVIOUS REPORT |
@nativescript-community/ui-pager@14.1.38 | @nativescript-community | ui-pager | 14.1.38 | PREVIOUS REPORT |
@nativescript-community/ui-pulltorefresh@2.5.4 | @nativescript-community | ui-pulltorefresh | 2.5.4 | PREVIOUS REPORT |
@nativescript-community/ui-pulltorefresh@2.5.5 | @nativescript-community | ui-pulltorefresh | 2.5.5 | PREVIOUS REPORT |
@nativescript-community/ui-pulltorefresh@2.5.6 | @nativescript-community | ui-pulltorefresh | 2.5.6 | PREVIOUS REPORT |
@nativescript-community/ui-pulltorefresh@2.5.7 | @nativescript-community | ui-pulltorefresh | 2.5.7 | PREVIOUS REPORT |
@nexe/config-manager@0.1.1 | @nexe | config-manager | 0.1.1 | PREVIOUS REPORT |
@nexe/eslint-config@0.1.1 | @nexe | eslint-config | 0.1.1 | PREVIOUS REPORT |
@nexe/logger@0.1.3 | @nexe | logger | 0.1.3 | PREVIOUS REPORT |
@nstudio/angular@20.0.4 | @nstudio | angular | 20.0.4 | PREVIOUS REPORT |
@nstudio/angular@20.0.5 | @nstudio | angular | 20.0.5 | PREVIOUS REPORT |
@nstudio/angular@20.0.6 | @nstudio | angular | 20.0.6 | PREVIOUS REPORT |
@nstudio/focus@20.0.4 | @nstudio | focus | 20.0.4 | PREVIOUS REPORT |
@nstudio/focus@20.0.5 | @nstudio | focus | 20.0.5 | PREVIOUS REPORT |
@nstudio/focus@20.0.6 | @nstudio | focus | 20.0.6 | PREVIOUS REPORT |
@nstudio/nativescript-checkbox@2.0.6 | @nstudio | nativescript-checkbox | 2.0.6 | PREVIOUS REPORT |
@nstudio/nativescript-checkbox@2.0.7 | @nstudio | nativescript-checkbox | 2.0.7 | PREVIOUS REPORT |
@nstudio/nativescript-checkbox@2.0.8 | @nstudio | nativescript-checkbox | 2.0.8 | PREVIOUS REPORT |
@nstudio/nativescript-checkbox@2.0.9 | @nstudio | nativescript-checkbox | 2.0.9 | PREVIOUS REPORT |
@nstudio/nativescript-loading-indicator@5.0.1 | @nstudio | nativescript-loading-indicator | 5.0.1 | PREVIOUS REPORT |
@nstudio/nativescript-loading-indicator@5.0.2 | @nstudio | nativescript-loading-indicator | 5.0.2 | PREVIOUS REPORT |
@nstudio/nativescript-loading-indicator@5.0.3 | @nstudio | nativescript-loading-indicator | 5.0.3 | PREVIOUS REPORT |
@nstudio/nativescript-loading-indicator@5.0.4 | @nstudio | nativescript-loading-indicator | 5.0.4 | PREVIOUS REPORT |
@nstudio/ui-collectionview@5.1.11 | @nstudio | ui-collectionview | 5.1.11 | PREVIOUS REPORT |
@nstudio/ui-collectionview@5.1.12 | @nstudio | ui-collectionview | 5.1.12 | PREVIOUS REPORT |
@nstudio/ui-collectionview@5.1.13 | @nstudio | ui-collectionview | 5.1.13 | PREVIOUS REPORT |
@nstudio/ui-collectionview@5.1.14 | @nstudio | ui-collectionview | 5.1.14 | PREVIOUS REPORT |
@nstudio/web-angular@20.0.4 | @nstudio | web-angular | 20.0.4 | PREVIOUS REPORT |
@nstudio/web@20.0.4 | @nstudio | web | 20.0.4 | PREVIOUS REPORT |
@nstudio/xplat-utils@20.0.5 | @nstudio | xplat-utils | 20.0.5 | PREVIOUS REPORT |
@nstudio/xplat-utils@20.0.6 | @nstudio | xplat-utils | 20.0.6 | PREVIOUS REPORT |
@nstudio/xplat-utils@20.0.7 | @nstudio | xplat-utils | 20.0.7 | PREVIOUS REPORT |
@nstudio/xplat@20.0.5 | @nstudio | xplat | 20.0.5 | PREVIOUS REPORT |
@nstudio/xplat@20.0.6 | @nstudio | xplat | 20.0.6 | PREVIOUS REPORT |
@nstudio/xplat@20.0.7 | @nstudio | xplat | 20.0.7 | PREVIOUS REPORT |
@operato/board@9.0.35 | @operato | board | 9.0.35 | PREVIOUS REPORT |
@operato/board@9.0.36 | @operato | board | 9.0.36 | PREVIOUS REPORT |
@operato/board@9.0.37 | @operato | board | 9.0.37 | PREVIOUS REPORT |
@operato/board@9.0.38 | @operato | board | 9.0.38 | PREVIOUS REPORT |
@operato/board@9.0.39 | @operato | board | 9.0.39 | PREVIOUS REPORT |
@operato/board@9.0.40 | @operato | board | 9.0.40 | PREVIOUS REPORT |
@operato/board@9.0.41 | @operato | board | 9.0.41 | PREVIOUS REPORT |
@operato/board@9.0.42 | @operato | board | 9.0.42 | PREVIOUS REPORT |
@operato/board@9.0.43 | @operato | board | 9.0.43 | PREVIOUS REPORT |
@operato/board@9.0.44 | @operato | board | 9.0.44 | PREVIOUS REPORT |
@operato/board@9.0.45 | @operato | board | 9.0.45 | PREVIOUS REPORT |
@operato/board@9.0.46 | @operato | board | 9.0.46 | PREVIOUS REPORT |
@operato/board@9.0.47 | @operato | board | 9.0.47 | PREVIOUS REPORT |
@operato/board@9.0.48 | @operato | board | 9.0.48 | PREVIOUS REPORT |
@operato/board@9.0.49 | @operato | board | 9.0.49 | PREVIOUS REPORT |
@operato/board@9.0.50 | @operato | board | 9.0.50 | PREVIOUS REPORT |
@operato/board@9.0.51 | @operato | board | 9.0.51 | PREVIOUS REPORT |
@operato/data-grist@9.0.29 | @operato | data-grist | 9.0.29 | PREVIOUS REPORT |
@operato/data-grist@9.0.35 | @operato | data-grist | 9.0.35 | PREVIOUS REPORT |
@operato/data-grist@9.0.36 | @operato | data-grist | 9.0.36 | PREVIOUS REPORT |
@operato/data-grist@9.0.37 | @operato | data-grist | 9.0.37 | PREVIOUS REPORT |
@operato/graphql@9.0.22 | @operato | graphql | 9.0.22 | PREVIOUS REPORT |
@operato/graphql@9.0.35 | @operato | graphql | 9.0.35 | PREVIOUS REPORT |
@operato/graphql@9.0.36 | @operato | graphql | 9.0.36 | PREVIOUS REPORT |
@operato/graphql@9.0.37 | @operato | graphql | 9.0.37 | PREVIOUS REPORT |
@operato/graphql@9.0.38 | @operato | graphql | 9.0.38 | PREVIOUS REPORT |
@operato/graphql@9.0.39 | @operato | graphql | 9.0.39 | PREVIOUS REPORT |
@operato/graphql@9.0.40 | @operato | graphql | 9.0.40 | PREVIOUS REPORT |
@operato/graphql@9.0.41 | @operato | graphql | 9.0.41 | PREVIOUS REPORT |
@operato/graphql@9.0.42 | @operato | graphql | 9.0.42 | PREVIOUS REPORT |
@operato/graphql@9.0.43 | @operato | graphql | 9.0.43 | PREVIOUS REPORT |
@operato/graphql@9.0.44 | @operato | graphql | 9.0.44 | PREVIOUS REPORT |
@operato/graphql@9.0.45 | @operato | graphql | 9.0.45 | PREVIOUS REPORT |
@operato/graphql@9.0.46 | @operato | graphql | 9.0.46 | PREVIOUS REPORT |
@operato/graphql@9.0.47 | @operato | graphql | 9.0.47 | NEW FINDING |
@operato/graphql@9.0.48 | @operato | graphql | 9.0.48 | NEW FINDING |
@operato/graphql@9.0.49 | @operato | graphql | 9.0.49 | NEW FINDING |
@operato/graphql@9.0.50 | @operato | graphql | 9.0.50 | NEW FINDING |
@operato/graphql@9.0.51 | @operato | graphql | 9.0.51 | NEW FINDING |
@operato/headroom@9.0.2 | @operato | headroom | 9.0.2 | PREVIOUS REPORT |
@operato/headroom@9.0.35 | @operato | headroom | 9.0.35 | PREVIOUS REPORT |
@operato/headroom@9.0.36 | @operato | headroom | 9.0.36 | PREVIOUS REPORT |
@operato/headroom@9.0.37 | @operato | headroom | 9.0.37 | PREVIOUS REPORT |
@operato/help@9.0.35 | @operato | help | 9.0.35 | PREVIOUS REPORT |
@operato/help@9.0.36 | @operato | help | 9.0.36 | PREVIOUS REPORT |
@operato/help@9.0.37 | @operato | help | 9.0.37 | PREVIOUS REPORT |
@operato/help@9.0.38 | @operato | help | 9.0.38 | PREVIOUS REPORT |
@operato/help@9.0.39 | @operato | help | 9.0.39 | PREVIOUS REPORT |
@operato/help@9.0.40 | @operato | help | 9.0.40 | PREVIOUS REPORT |
@operato/help@9.0.41 | @operato | help | 9.0.41 | PREVIOUS REPORT |
@operato/help@9.0.42 | @operato | help | 9.0.42 | PREVIOUS REPORT |
@operato/help@9.0.43 | @operato | help | 9.0.43 | PREVIOUS REPORT |
@operato/help@9.0.44 | @operato | help | 9.0.44 | PREVIOUS REPORT |
@operato/help@9.0.45 | @operato | help | 9.0.45 | PREVIOUS REPORT |
@operato/help@9.0.46 | @operato | help | 9.0.46 | PREVIOUS REPORT |
@operato/help@9.0.47 | @operato | help | 9.0.47 | NEW FINDING |
@operato/help@9.0.48 | @operato | help | 9.0.48 | NEW FINDING |
@operato/help@9.0.49 | @operato | help | 9.0.49 | NEW FINDING |
@operato/help@9.0.50 | @operato | help | 9.0.50 | NEW FINDING |
@operato/help@9.0.51 | @operato | help | 9.0.51 | NEW FINDING |
@operato/i18n@9.0.35 | @operato | i18n | 9.0.35 | PREVIOUS REPORT |
@operato/i18n@9.0.36 | @operato | i18n | 9.0.36 | PREVIOUS REPORT |
@operato/i18n@9.0.37 | @operato | i18n | 9.0.37 | PREVIOUS REPORT |
@operato/input@9.0.27 | @operato | input | 9.0.27 | PREVIOUS REPORT |
@operato/input@9.0.35 | @operato | input | 9.0.35 | PREVIOUS REPORT |
@operato/input@9.0.36 | @operato | input | 9.0.36 | PREVIOUS REPORT |
@operato/input@9.0.37 | @operato | input | 9.0.37 | PREVIOUS REPORT |
@operato/input@9.0.38 | @operato | input | 9.0.38 | PREVIOUS REPORT |
@operato/input@9.0.39 | @operato | input | 9.0.39 | PREVIOUS REPORT |
@operato/input@9.0.40 | @operato | input | 9.0.40 | PREVIOUS REPORT |
@operato/input@9.0.41 | @operato | input | 9.0.41 | PREVIOUS REPORT |
@operato/input@9.0.42 | @operato | input | 9.0.42 | PREVIOUS REPORT |
@operato/input@9.0.43 | @operato | input | 9.0.43 | PREVIOUS REPORT |
@operato/input@9.0.44 | @operato | input | 9.0.44 | PREVIOUS REPORT |
@operato/input@9.0.45 | @operato | input | 9.0.45 | PREVIOUS REPORT |
@operato/input@9.0.46 | @operato | input | 9.0.46 | PREVIOUS REPORT |
@operato/input@9.0.47 | @operato | input | 9.0.47 | PREVIOUS REPORT |
@operato/input@9.0.48 | @operato | input | 9.0.48 | PREVIOUS REPORT |
@operato/layout@9.0.35 | @operato | layout | 9.0.35 | PREVIOUS REPORT |
@operato/layout@9.0.36 | @operato | layout | 9.0.36 | PREVIOUS REPORT |
@operato/layout@9.0.37 | @operato | layout | 9.0.37 | PREVIOUS REPORT |
@operato/popup@9.0.22 | @operato | popup | 9.0.22 | PREVIOUS REPORT |
@operato/popup@9.0.35 | @operato | popup | 9.0.35 | PREVIOUS REPORT |
@operato/popup@9.0.36 | @operato | popup | 9.0.36 | PREVIOUS REPORT |
@operato/popup@9.0.37 | @operato | popup | 9.0.37 | PREVIOUS REPORT |
@operato/popup@9.0.38 | @operato | popup | 9.0.38 | PREVIOUS REPORT |
@operato/popup@9.0.39 | @operato | popup | 9.0.39 | PREVIOUS REPORT |
@operato/popup@9.0.40 | @operato | popup | 9.0.40 | PREVIOUS REPORT |
@operato/popup@9.0.41 | @operato | popup | 9.0.41 | PREVIOUS REPORT |
@operato/popup@9.0.42 | @operato | popup | 9.0.42 | PREVIOUS REPORT |
@operato/popup@9.0.43 | @operato | popup | 9.0.43 | PREVIOUS REPORT |
@operato/popup@9.0.44 | @operato | popup | 9.0.44 | PREVIOUS REPORT |
@operato/popup@9.0.45 | @operato | popup | 9.0.45 | PREVIOUS REPORT |
@operato/popup@9.0.46 | @operato | popup | 9.0.46 | PREVIOUS REPORT |
@operato/popup@9.0.47 | @operato | popup | 9.0.47 | NEW FINDING |
@operato/popup@9.0.48 | @operato | popup | 9.0.48 | NEW FINDING |
@operato/popup@9.0.49 | @operato | popup | 9.0.49 | PREVIOUS REPORT |
@operato/popup@9.0.50 | @operato | popup | 9.0.50 | NEW FINDING |
@operato/popup@9.0.51 | @operato | popup | 9.0.51 | NEW FINDING |
@operato/pull-to-refresh@9.0.35 | @operato | pull-to-refresh | 9.0.35 | NEW FINDING |
@operato/pull-to-refresh@9.0.36 | @operato | pull-to-refresh | 9.0.36 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.37 | @operato | pull-to-refresh | 9.0.37 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.38 | @operato | pull-to-refresh | 9.0.38 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.39 | @operato | pull-to-refresh | 9.0.39 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.40 | @operato | pull-to-refresh | 9.0.40 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.41 | @operato | pull-to-refresh | 9.0.41 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.42 | @operato | pull-to-refresh | 9.0.42 | PREVIOUS REPORT |
@operato/pull-to-refresh@9.0.43 | @operato | pull-to-refresh | 9.0.43 | NEW FINDING |
@operato/pull-to-refresh@9.0.44 | @operato | pull-to-refresh | 9.0.44 | NEW FINDING |
@operato/pull-to-refresh@9.0.45 | @operato | pull-to-refresh | 9.0.45 | NEW FINDING |
@operato/pull-to-refresh@9.0.46 | @operato | pull-to-refresh | 9.0.46 | NEW FINDING |
@operato/pull-to-refresh@9.0.47 | @operato | pull-to-refresh | 9.0.47 | NEW FINDING |
@operato/shell@9.0.22 | @operato | shell | 9.0.22 | PREVIOUS REPORT |
@operato/shell@9.0.35 | @operato | shell | 9.0.35 | PREVIOUS REPORT |
@operato/shell@9.0.36 | @operato | shell | 9.0.36 | PREVIOUS REPORT |
@operato/shell@9.0.37 | @operato | shell | 9.0.37 | PREVIOUS REPORT |
@operato/shell@9.0.38 | @operato | shell | 9.0.38 | PREVIOUS REPORT |
@operato/shell@9.0.39 | @operato | shell | 9.0.39 | PREVIOUS REPORT |
@operato/styles@9.0.2 | @operato | styles | 9.0.2 | PREVIOUS REPORT |
@operato/styles@9.0.35 | @operato | styles | 9.0.35 | PREVIOUS REPORT |
@operato/styles@9.0.36 | @operato | styles | 9.0.36 | PREVIOUS REPORT |
@operato/styles@9.0.37 | @operato | styles | 9.0.37 | PREVIOUS REPORT |
@operato/utils@9.0.22 | @operato | utils | 9.0.22 | PREVIOUS REPORT |
@operato/utils@9.0.35 | @operato | utils | 9.0.35 | PREVIOUS REPORT |
@operato/utils@9.0.36 | @operato | utils | 9.0.36 | PREVIOUS REPORT |
@operato/utils@9.0.37 | @operato | utils | 9.0.37 | PREVIOUS REPORT |
@operato/utils@9.0.38 | @operato | utils | 9.0.38 | PREVIOUS REPORT |
@operato/utils@9.0.39 | @operato | utils | 9.0.39 | PREVIOUS REPORT |
@operato/utils@9.0.40 | @operato | utils | 9.0.40 | PREVIOUS REPORT |
@operato/utils@9.0.41 | @operato | utils | 9.0.41 | PREVIOUS REPORT |
@operato/utils@9.0.42 | @operato | utils | 9.0.42 | PREVIOUS REPORT |
@operato/utils@9.0.43 | @operato | utils | 9.0.43 | PREVIOUS REPORT |
@operato/utils@9.0.44 | @operato | utils | 9.0.44 | PREVIOUS REPORT |
@operato/utils@9.0.45 | @operato | utils | 9.0.45 | PREVIOUS REPORT |
@operato/utils@9.0.46 | @operato | utils | 9.0.46 | PREVIOUS REPORT |
@operato/utils@9.0.47 | @operato | utils | 9.0.47 | PREVIOUS REPORT |
@operato/utils@9.0.48 | @operato | utils | 9.0.48 | NEW FINDING |
@operato/utils@9.0.49 | @operato | utils | 9.0.49 | PREVIOUS REPORT |
@operato/utils@9.0.50 | @operato | utils | 9.0.50 | PREVIOUS REPORT |
@operato/utils@9.0.51 | @operato | utils | 9.0.51 | PREVIOUS REPORT |
@rxap/ngx-bootstrap@19.0.3 | @rxap | ngx-bootstrap | 19.0.3 | PREVIOUS REPORT |
@rxap/ngx-bootstrap@19.0.4 | @rxap | ngx-bootstrap | 19.0.4 | PREVIOUS REPORT |
@teriyakibomb/ember-velcro@2.2.1 | @teriyakibomb | ember-velcro | 2.2.1 | NEW FINDING |
@teselagen/bio-parsers@0.4.30 | @teselagen | bio-parsers | 0.4.30 | PREVIOUS REPORT |
@teselagen/bounce-loader@0.3.16 | @teselagen | bounce-loader | 0.3.16 | PREVIOUS REPORT |
@teselagen/bounce-loader@0.3.17 | @teselagen | bounce-loader | 0.3.17 | PREVIOUS REPORT |
@teselagen/file-utils@0.3.22 | @teselagen | file-utils | 0.3.22 | PREVIOUS REPORT |
@teselagen/liquibase-tools@0.4.1 | @teselagen | liquibase-tools | 0.4.1 | PREVIOUS REPORT |
@teselagen/ove@0.7.40 | @teselagen | ove | 0.7.40 | PREVIOUS REPORT |
@teselagen/range-utils@0.3.14 | @teselagen | range-utils | 0.3.14 | PREVIOUS REPORT |
@teselagen/range-utils@0.3.15 | @teselagen | range-utils | 0.3.15 | PREVIOUS REPORT |
@teselagen/react-list@0.8.19 | @teselagen | react-list | 0.8.19 | PREVIOUS REPORT |
@teselagen/react-list@0.8.20 | @teselagen | react-list | 0.8.20 | PREVIOUS REPORT |
@teselagen/react-table@6.10.19 | @teselagen | react-table | 6.10.19 | PREVIOUS REPORT |
@teselagen/react-table@6.10.20 | @teselagen | react-table | 6.10.20 | PREVIOUS REPORT |
@teselagen/react-table@6.10.22 | @teselagen | react-table | 6.10.22 | PREVIOUS REPORT |
@teselagen/sequence-utils@0.3.34 | @teselagen | sequence-utils | 0.3.34 | PREVIOUS REPORT |
@teselagen/ui@0.9.10 | @teselagen | ui | 0.9.10 | PREVIOUS REPORT |
@thangved/callback-window@1.1.4 | @thangved | callback-window | 1.1.4 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.42 | @things-factory | attachment-base | 9.0.42 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.43 | @things-factory | attachment-base | 9.0.43 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.44 | @things-factory | attachment-base | 9.0.44 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.45 | @things-factory | attachment-base | 9.0.45 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.46 | @things-factory | attachment-base | 9.0.46 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.47 | @things-factory | attachment-base | 9.0.47 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.48 | @things-factory | attachment-base | 9.0.48 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.49 | @things-factory | attachment-base | 9.0.49 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.50 | @things-factory | attachment-base | 9.0.50 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.51 | @things-factory | attachment-base | 9.0.51 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.52 | @things-factory | attachment-base | 9.0.52 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.53 | @things-factory | attachment-base | 9.0.53 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.54 | @things-factory | attachment-base | 9.0.54 | PREVIOUS REPORT |
@things-factory/attachment-base@9.0.55 | @things-factory | attachment-base | 9.0.55 | PREVIOUS REPORT |
@things-factory/auth-base@9.0.42 | @things-factory | auth-base | 9.0.42 | PREVIOUS REPORT |
@things-factory/auth-base@9.0.43 | @things-factory | auth-base | 9.0.43 | PREVIOUS REPORT |
@things-factory/auth-base@9.0.44 | @things-factory | auth-base | 9.0.44 | PREVIOUS REPORT |
@things-factory/auth-base@9.0.45 | @things-factory | auth-base | 9.0.45 | PREVIOUS REPORT |
@things-factory/email-base@9.0.42 | @things-factory | email-base | 9.0.42 | PREVIOUS REPORT |
@things-factory/email-base@9.0.43 | @things-factory | email-base | 9.0.43 | PREVIOUS REPORT |
@things-factory/email-base@9.0.44 | @things-factory | email-base | 9.0.44 | PREVIOUS REPORT |
@things-factory/email-base@9.0.45 | @things-factory | email-base | 9.0.45 | PREVIOUS REPORT |
@things-factory/email-base@9.0.46 | @things-factory | email-base | 9.0.46 | PREVIOUS REPORT |
@things-factory/email-base@9.0.47 | @things-factory | email-base | 9.0.47 | PREVIOUS REPORT |
@things-factory/email-base@9.0.48 | @things-factory | email-base | 9.0.48 | PREVIOUS REPORT |
@things-factory/email-base@9.0.49 | @things-factory | email-base | 9.0.49 | PREVIOUS REPORT |
@things-factory/email-base@9.0.50 | @things-factory | email-base | 9.0.50 | PREVIOUS REPORT |
@things-factory/email-base@9.0.51 | @things-factory | email-base | 9.0.51 | PREVIOUS REPORT |
@things-factory/email-base@9.0.52 | @things-factory | email-base | 9.0.52 | PREVIOUS REPORT |
@things-factory/email-base@9.0.53 | @things-factory | email-base | 9.0.53 | PREVIOUS REPORT |
@things-factory/email-base@9.0.54 | @things-factory | email-base | 9.0.54 | PREVIOUS REPORT |
@things-factory/email-base@9.0.55 | @things-factory | email-base | 9.0.55 | PREVIOUS REPORT |
@things-factory/email-base@9.0.56 | @things-factory | email-base | 9.0.56 | PREVIOUS REPORT |
@things-factory/email-base@9.0.57 | @things-factory | email-base | 9.0.57 | PREVIOUS REPORT |
@things-factory/email-base@9.0.58 | @things-factory | email-base | 9.0.58 | PREVIOUS REPORT |
@things-factory/email-base@9.0.59 | @things-factory | email-base | 9.0.59 | PREVIOUS REPORT |
@things-factory/env@9.0.42 | @things-factory | env | 9.0.42 | PREVIOUS REPORT |
@things-factory/env@9.0.43 | @things-factory | env | 9.0.43 | PREVIOUS REPORT |
@things-factory/env@9.0.44 | @things-factory | env | 9.0.44 | PREVIOUS REPORT |
@things-factory/env@9.0.45 | @things-factory | env | 9.0.45 | PREVIOUS REPORT |
@things-factory/integration-base@9.0.42 | @things-factory | integration-base | 9.0.42 | PREVIOUS REPORT |
@things-factory/integration-base@9.0.43 | @things-factory | integration-base | 9.0.43 | PREVIOUS REPORT |
@things-factory/integration-base@9.0.44 | @things-factory | integration-base | 9.0.44 | PREVIOUS REPORT |
@things-factory/integration-base@9.0.45 | @things-factory | integration-base | 9.0.45 | PREVIOUS REPORT |
@things-factory/integration-marketplace@9.0.43 | @things-factory | integration-marketplace | 9.0.43 | PREVIOUS REPORT |
@things-factory/integration-marketplace@9.0.44 | @things-factory | integration-marketplace | 9.0.44 | PREVIOUS REPORT |
@things-factory/integration-marketplace@9.0.45 | @things-factory | integration-marketplace | 9.0.45 | PREVIOUS REPORT |
@things-factory/shell@9.0.42 | @things-factory | shell | 9.0.42 | PREVIOUS REPORT |
@things-factory/shell@9.0.43 | @things-factory | shell | 9.0.43 | PREVIOUS REPORT |
@things-factory/shell@9.0.44 | @things-factory | shell | 9.0.44 | PREVIOUS REPORT |
@things-factory/shell@9.0.45 | @things-factory | shell | 9.0.45 | PREVIOUS REPORT |
@tnf-dev/api@1.0.8 | @tnf-dev | api | 1.0.8 | PREVIOUS REPORT |
@tnf-dev/core@1.0.8 | @tnf-dev | core | 1.0.8 | PREVIOUS REPORT |
@tnf-dev/js@1.0.8 | @tnf-dev | js | 1.0.8 | PREVIOUS REPORT |
@tnf-dev/mui@1.0.8 | @tnf-dev | mui | 1.0.8 | PREVIOUS REPORT |
@tnf-dev/react@1.0.8 | @tnf-dev | react | 1.0.8 | PREVIOUS REPORT |
@ui-ux-gang/devextreme-angular-rpk@24.1.7 | @ui-ux-gang | devextreme-angular-rpk | 24.1.7 | PREVIOUS REPORT |
@yoobic/design-system@6.5.17 | @yoobic | design-system | 6.5.17 | PREVIOUS REPORT |
@yoobic/jpeg-camera-es6@1.0.13 | @yoobic | jpeg-camera-es6 | 1.0.13 | PREVIOUS REPORT |
@yoobic/yobi@8.7.53 | @yoobic | yobi | 8.7.53 | PREVIOUS REPORT |
airchief@0.3.1 | airchief | 0.3.1 | PREVIOUS REPORT | |
airpilot@0.8.8 | airpilot | 0.8.8 | PREVIOUS REPORT | |
angulartics2@14.1.1 | angulartics2 | 14.1.1 | PREVIOUS REPORT | |
angulartics2@14.1.2 | angulartics2 | 14.1.2 | PREVIOUS REPORT | |
another-shai@1.0.1 | another-shai | 1.0.1 | PREVIOUS REPORT | |
browser-webdriver-downloader@3.0.8 | browser-webdriver-downloader | 3.0.8 | PREVIOUS REPORT | |
capacitor-notificationhandler@0.0.2 | capacitor-notificationhandler | 0.0.2 | PREVIOUS REPORT | |
capacitor-notificationhandler@0.0.3 | capacitor-notificationhandler | 0.0.3 | PREVIOUS REPORT | |
capacitor-plugin-healthapp@0.0.2 | capacitor-plugin-healthapp | 0.0.2 | PREVIOUS REPORT | |
capacitor-plugin-healthapp@0.0.3 | capacitor-plugin-healthapp | 0.0.3 | PREVIOUS REPORT | |
capacitor-plugin-ihealth@1.1.8 | capacitor-plugin-ihealth | 1.1.8 | PREVIOUS REPORT | |
capacitor-plugin-ihealth@1.1.9 | capacitor-plugin-ihealth | 1.1.9 | PREVIOUS REPORT | |
capacitor-plugin-vonage@1.0.2 | capacitor-plugin-vonage | 1.0.2 | PREVIOUS REPORT | |
capacitor-plugin-vonage@1.0.3 | capacitor-plugin-vonage | 1.0.3 | PREVIOUS REPORT | |
capacitorandroidpermissions@0.0.4 | capacitorandroidpermissions | 0.0.4 | PREVIOUS REPORT | |
capacitorandroidpermissions@0.0.5 | capacitorandroidpermissions | 0.0.5 | PREVIOUS REPORT | |
config-cordova@0.8.5 | config-cordova | 0.8.5 | PREVIOUS REPORT | |
cordova-plugin-voxeet2@1.0.24 | cordova-plugin-voxeet2 | 1.0.24 | PREVIOUS REPORT | |
cordova-voxeet@1.0.32 | cordova-voxeet | 1.0.32 | PREVIOUS REPORT | |
create-hest-app@0.1.9 | create-hest-app | 0.1.9 | PREVIOUS REPORT | |
db-evo@1.1.4 | db-evo | 1.1.4 | PREVIOUS REPORT | |
db-evo@1.1.5 | db-evo | 1.1.5 | PREVIOUS REPORT | |
devextreme-angular-rpk@21.2.8 | devextreme-angular-rpk | 21.2.8 | PREVIOUS REPORT | |
ember-browser-services@5.0.2 | ember-browser-services | 5.0.2 | PREVIOUS REPORT | |
ember-browser-services@5.0.3 | ember-browser-services | 5.0.3 | PREVIOUS REPORT | |
ember-headless-form-yup@1.0.1 | ember-headless-form-yup | 1.0.1 | PREVIOUS REPORT | |
ember-headless-form@1.1.2 | ember-headless-form | 1.1.2 | PREVIOUS REPORT | |
ember-headless-form@1.1.3 | ember-headless-form | 1.1.3 | PREVIOUS REPORT | |
ember-headless-table@2.1.5 | ember-headless-table | 2.1.5 | PREVIOUS REPORT | |
ember-headless-table@2.1.6 | ember-headless-table | 2.1.6 | PREVIOUS REPORT | |
ember-url-hash-polyfill@1.0.12 | ember-url-hash-polyfill | 1.0.12 | PREVIOUS REPORT | |
ember-url-hash-polyfill@1.0.13 | ember-url-hash-polyfill | 1.0.13 | PREVIOUS REPORT | |
ember-velcro@2.2.1 | ember-velcro | 2.2.1 | PREVIOUS REPORT | |
ember-velcro@2.2.2 | ember-velcro | 2.2.2 | PREVIOUS REPORT | |
encounter-playground@0.0.2 | encounter-playground | 0.0.2 | PREVIOUS REPORT | |
encounter-playground@0.0.3 | encounter-playground | 0.0.3 | PREVIOUS REPORT | |
encounter-playground@0.0.4 | encounter-playground | 0.0.4 | PREVIOUS REPORT | |
encounter-playground@0.0.5 | encounter-playground | 0.0.5 | PREVIOUS REPORT | |
eslint-config-crowdstrike-node@4.0.3 | eslint-config-crowdstrike-node | 4.0.3 | PREVIOUS REPORT | |
eslint-config-crowdstrike-node@4.0.4 | eslint-config-crowdstrike-node | 4.0.4 | PREVIOUS REPORT | |
eslint-config-crowdstrike@11.0.2 | eslint-config-crowdstrike | 11.0.2 | PREVIOUS REPORT | |
eslint-config-crowdstrike@11.0.3 | eslint-config-crowdstrike | 11.0.3 | PREVIOUS REPORT | |
eslint-config-teselagen@6.1.7 | eslint-config-teselagen | 6.1.7 | PREVIOUS REPORT | |
eslint-config-teselagen@6.1.8 | eslint-config-teselagen | 6.1.8 | PREVIOUS REPORT | |
globalize-rpk@1.7.4 | globalize-rpk | 1.7.4 | PREVIOUS REPORT | |
graphql-sequelize-teselagen@5.3.8 | graphql-sequelize-teselagen | 5.3.8 | PREVIOUS REPORT | |
graphql-sequelize-teselagen@5.3.9 | graphql-sequelize-teselagen | 5.3.9 | PREVIOUS REPORT | |
html-to-base64-image@1.0.2 | html-to-base64-image | 1.0.2 | PREVIOUS REPORT | |
json-rules-engine-simplified@0.2.1 | json-rules-engine-simplified | 0.2.1 | PREVIOUS REPORT | |
json-rules-engine-simplified@0.2.4 | json-rules-engine-simplified | 0.2.4 | PREVIOUS REPORT | |
jumpgate@0.0.2 | jumpgate | 0.0.2 | PREVIOUS REPORT | |
koa2-swagger-ui@5.11.1 | koa2-swagger-ui | 5.11.1 | PREVIOUS REPORT | |
koa2-swagger-ui@5.11.2 | koa2-swagger-ui | 5.11.2 | PREVIOUS REPORT | |
mcfly-semantic-release@1.3.1 | mcfly-semantic-release | 1.3.1 | PREVIOUS REPORT | |
mcp-knowledge-base@0.0.2 | mcp-knowledge-base | 0.0.2 | PREVIOUS REPORT | |
mcp-knowledge-graph@1.2.1 | mcp-knowledge-graph | 1.2.1 | PREVIOUS REPORT | |
mobioffice-cli@1.0.3 | mobioffice-cli | 1.0.3 | PREVIOUS REPORT | |
monorepo-next@13.0.1 | monorepo-next | 13.0.1 | PREVIOUS REPORT | |
monorepo-next@13.0.2 | monorepo-next | 13.0.2 | PREVIOUS REPORT | |
mstate-angular@0.4.4 | mstate-angular | 0.4.4 | PREVIOUS REPORT | |
mstate-cli@0.4.7 | mstate-cli | 0.4.7 | PREVIOUS REPORT | |
mstate-dev-react@1.1.1 | mstate-dev-react | 1.1.1 | PREVIOUS REPORT | |
mstate-react@1.6.5 | mstate-react | 1.6.5 | PREVIOUS REPORT | |
ng2-file-upload@7.0.2 | ng2-file-upload | 7.0.2 | PREVIOUS REPORT | |
ng2-file-upload@7.0.3 | ng2-file-upload | 7.0.3 | PREVIOUS REPORT | |
ng2-file-upload@8.0.1 | ng2-file-upload | 8.0.1 | PREVIOUS REPORT | |
ng2-file-upload@8.0.2 | ng2-file-upload | 8.0.2 | PREVIOUS REPORT | |
ng2-file-upload@8.0.3 | ng2-file-upload | 8.0.3 | PREVIOUS REPORT | |
ng2-file-upload@9.0.1 | ng2-file-upload | 9.0.1 | PREVIOUS REPORT | |
ngx-bootstrap@18.1.4 | ngx-bootstrap | 18.1.4 | PREVIOUS REPORT | |
ngx-bootstrap@19.0.3 | ngx-bootstrap | 19.0.3 | PREVIOUS REPORT | |
ngx-bootstrap@19.0.4 | ngx-bootstrap | 19.0.4 | PREVIOUS REPORT | |
ngx-bootstrap@20.0.3 | ngx-bootstrap | 20.0.3 | PREVIOUS REPORT | |
ngx-bootstrap@20.0.4 | ngx-bootstrap | 20.0.4 | PREVIOUS REPORT | |
ngx-bootstrap@20.0.5 | ngx-bootstrap | 20.0.5 | PREVIOUS REPORT | |
ngx-color@10.0.1 | ngx-color | 10.0.1 | PREVIOUS REPORT | |
ngx-color@10.0.2 | ngx-color | 10.0.2 | PREVIOUS REPORT | |
ngx-toastr@19.0.1 | ngx-toastr | 19.0.1 | PREVIOUS REPORT | |
ngx-toastr@19.0.2 | ngx-toastr | 19.0.2 | PREVIOUS REPORT | |
ngx-trend@8.0.1 | ngx-trend | 8.0.1 | PREVIOUS REPORT | |
ngx-ws@1.1.5 | ngx-ws | 1.1.5 | PREVIOUS REPORT | |
ngx-ws@1.1.6 | ngx-ws | 1.1.6 | PREVIOUS REPORT | |
oradm-to-gql@35.0.14 | oradm-to-gql | 35.0.14 | PREVIOUS REPORT | |
oradm-to-gql@35.0.15 | oradm-to-gql | 35.0.15 | PREVIOUS REPORT | |
oradm-to-sqlz@1.1.2 | oradm-to-sqlz | 1.1.2 | PREVIOUS REPORT | |
ove-auto-annotate@0.0.10 | ove-auto-annotate | 0.0.10 | PREVIOUS REPORT | |
ove-auto-annotate@0.0.9 | ove-auto-annotate | 0.0.9 | PREVIOUS REPORT | |
pm2-gelf-json@1.0.4 | pm2-gelf-json | 1.0.4 | PREVIOUS REPORT | |
pm2-gelf-json@1.0.5 | pm2-gelf-json | 1.0.5 | PREVIOUS REPORT | |
printjs-rpk@1.6.1 | printjs-rpk | 1.6.1 | PREVIOUS REPORT | |
react-complaint-image@0.0.32 | react-complaint-image | 0.0.32 | PREVIOUS REPORT | |
react-complaint-image@0.0.35 | react-complaint-image | 0.0.35 | PREVIOUS REPORT | |
react-jsonschema-form-conditionals@0.3.18 | react-jsonschema-form-conditionals | 0.3.18 | PREVIOUS REPORT | |
react-jsonschema-form-conditionals@0.3.21 | react-jsonschema-form-conditionals | 0.3.21 | PREVIOUS REPORT | |
react-jsonschema-form-extras@1.0.4 | react-jsonschema-form-extras | 1.0.4 | PREVIOUS REPORT | |
react-jsonschema-rxnt-extras@0.4.9 | react-jsonschema-rxnt-extras | 0.4.9 | PREVIOUS REPORT | |
remark-preset-lint-crowdstrike@4.0.1 | remark-preset-lint-crowdstrike | 4.0.1 | PREVIOUS REPORT | |
remark-preset-lint-crowdstrike@4.0.2 | remark-preset-lint-crowdstrike | 4.0.2 | PREVIOUS REPORT | |
rxnt-authentication@0.0.3 | rxnt-authentication | 0.0.3 | PREVIOUS REPORT | |
rxnt-authentication@0.0.4 | rxnt-authentication | 0.0.4 | PREVIOUS REPORT | |
rxnt-authentication@0.0.5 | rxnt-authentication | 0.0.5 | PREVIOUS REPORT | |
rxnt-authentication@0.0.6 | rxnt-authentication | 0.0.6 | PREVIOUS REPORT | |
rxnt-healthchecks-nestjs@1.0.2 | rxnt-healthchecks-nestjs | 1.0.2 | PREVIOUS REPORT | |
rxnt-healthchecks-nestjs@1.0.3 | rxnt-healthchecks-nestjs | 1.0.3 | PREVIOUS REPORT | |
rxnt-healthchecks-nestjs@1.0.4 | rxnt-healthchecks-nestjs | 1.0.4 | PREVIOUS REPORT | |
rxnt-healthchecks-nestjs@1.0.5 | rxnt-healthchecks-nestjs | 1.0.5 | PREVIOUS REPORT | |
rxnt-kue@1.0.4 | rxnt-kue | 1.0.4 | PREVIOUS REPORT | |
rxnt-kue@1.0.5 | rxnt-kue | 1.0.5 | PREVIOUS REPORT | |
rxnt-kue@1.0.6 | rxnt-kue | 1.0.6 | PREVIOUS REPORT | |
rxnt-kue@1.0.7 | rxnt-kue | 1.0.7 | PREVIOUS REPORT | |
swc-plugin-component-annotate@1.9.1 | swc-plugin-component-annotate | 1.9.1 | PREVIOUS REPORT | |
swc-plugin-component-annotate@1.9.2 | swc-plugin-component-annotate | 1.9.2 | PREVIOUS REPORT | |
tbssnch@1.0.2 | tbssnch | 1.0.2 | PREVIOUS REPORT | |
teselagen-interval-tree@1.1.2 | teselagen-interval-tree | 1.1.2 | PREVIOUS REPORT | |
tg-client-query-builder@2.14.4 | tg-client-query-builder | 2.14.4 | PREVIOUS REPORT | |
tg-client-query-builder@2.14.5 | tg-client-query-builder | 2.14.5 | PREVIOUS REPORT | |
tg-redbird@1.3.1 | tg-redbird | 1.3.1 | PREVIOUS REPORT | |
tg-redbird@1.3.2 | tg-redbird | 1.3.2 | PREVIOUS REPORT | |
tg-seq-gen@1.0.10 | tg-seq-gen | 1.0.10 | PREVIOUS REPORT | |
tg-seq-gen@1.0.9 | tg-seq-gen | 1.0.9 | PREVIOUS REPORT | |
thangved-react-grid@1.0.3 | thangved-react-grid | 1.0.3 | PREVIOUS REPORT | |
ts-gaussian@3.0.5 | ts-gaussian | 3.0.5 | PREVIOUS REPORT | |
ts-gaussian@3.0.6 | ts-gaussian | 3.0.6 | PREVIOUS REPORT | |
ts-imports@1.0.1 | ts-imports | 1.0.1 | PREVIOUS REPORT | |
ts-imports@1.0.2 | ts-imports | 1.0.2 | PREVIOUS REPORT | |
tvi-cli@0.1.5 | tvi-cli | 0.1.5 | PREVIOUS REPORT | |
ve-bamreader@0.2.6 | ve-bamreader | 0.2.6 | PREVIOUS REPORT | |
ve-bamreader@0.2.7 | ve-bamreader | 0.2.7 | PREVIOUS REPORT | |
ve-editor@1.0.1 | ve-editor | 1.0.1 | PREVIOUS REPORT | |
ve-editor@1.0.2 | ve-editor | 1.0.2 | PREVIOUS REPORT | |
verror-extra@6.0.1 | verror-extra | 6.0.1 | PREVIOUS REPORT | |
voip-callkit@1.0.2 | voip-callkit | 1.0.2 | PREVIOUS REPORT | |
voip-callkit@1.0.3 | voip-callkit | 1.0.3 | PREVIOUS REPORT | |
wdio-web-reporter@0.1.3 | wdio-web-reporter | 0.1.3 | PREVIOUS REPORT | |
yargs-help-output@5.0.3 | yargs-help-output | 5.0.3 | PREVIOUS REPORT | |
yoo-styles@6.0.326 | yoo-styles | 6.0.326 | PREVIOUS REPORT |
The payload under the microscope
Stage 1: Recon and environment sweep
- OS/arch profile using os.platform() and os.arch() to tailor a TruffleHog download.
- Env dump to harvest any exported credentials: GITHUB_TOKEN, NPM_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, cloud CLI creds, and CI secrets that occasionally leak into runner envs.
Stage 2: Secrets harvesting
- Local filesystem scan: invokes TruffleHog as a child process (filesystem / –json) to trawl for high-entropy secrets across developer machines or CI agents.
- Cloud secret managers: enumerates AWS Secrets Manager and GCP Secret Manager, with pagination and silent error handling. This is notable—many “npm malware” strains stop at environment variables; this one reaches into managed secret stores if credentials are present.
Stage 3: Token validation and lateral reach
- npm identity: /-/whoami used to confirm token validity, then the code pivots to maintainer package discovery via registry search.
- GitHub reach: if a token exists, calls /user and repo APIs, plants a workflow, and creates branches to persist the backdoor beyond the original host.
Stage 4: Persistence via GitHub Actions
- Workflow path: .github/workflows/shai-hulud-workflow.yml.
- Function: serialize secrets, double- or triple-base64 content, and POST to a webhook[.]site collector.
- Risk: once committed, any future CI run leaks secrets again. Token rotation alone won’t save you unless you also remove the workflow and force a clean history.
Indicators of Compromise (IoCs)
- Malicious file: bundle.js
SHA-256: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09 - 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
- de0e25a3e6c1e1e5998b306b7141b3dc4c0088da9d7bb47c1c00c91e6e4f85d6
- 81d2a004a1bca6ef87a1caf7d0e0b355ad1764238e40ff6d1b1cb77ad4f595c3
- 83a650ce44b2a9854802a7fb4c202877815274c129af49e6c2d1d5d5d55c501e
- 4b2399646573bb737c4969563303d8ee2e9ddbd1b271f1ca9e35ea78062538db
- dc67467a39b70d1cd4c1f7f7a459b35058163592f4a9e8fb4dffcbba98ef210c
- 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
- b74caeaa75e077c99f7d44f46daaf9796a3be43ecf24f2a1fd381844669da777
- Backdoor workflow: .github/workflows/shai-hulud-workflow.yml
- C2 / exfil: https://webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7 (defang if sharing internally).
- Suspicious behaviors: npm publish –force, TruffleHog invocation filesystem / –json, npm registry maintainer search (/v1/search?text=maintainer:), GitHub repo and contents writes, secretsmanager API calls. (link to Socket)
Immediate response playbook (copy/paste friendly)
1) Hunt and eradicate the packages
# Check for affected packages (example: tinycolor)
npm ls @ctrl/tinycolor
# Force remove compromised versions (replace with your offenders)
npm uninstall @ctrl/tinycolor
npm cache verify
Cross-check your lockfiles for any of the versions listed above; pin to known-good releases and re-vendor locks.
Note that this checks only first-level dependencies
2) Remove the GitHub Actions backdoor
# From each repo’s root
rm -f .github/workflows/shai-hulud-workflow.yml
# Look for a lingering branch across all repos in an org
gh repo list YOUR_ORG –limit 1000 –json nameWithOwner –jq ‘.[].nameWithOwner’ \
| while read repo; do
gh api “repos/$repo/branches” –jq ‘.[] | select(.name == “shai-hulud”) | “‘$repo’ has branch: ” + .name’
done
# If found, delete it
git push origin –delete shai-hulud
The persistence risk sits in CI. Scrub workflow files in all repos, including forks and archived projects where secrets still live.
3) Rotate credentials with blast-radius thinking
- GitHub: personal access tokens, Actions secrets (org, env, repo), deploy keys, OAuth app grants.
- npm: automation tokens and publish tokens—replace ~/.npmrc everywhere.
- Cloud: AWS IAM keys, GCP SA keys, Azure SP credentials; regenerate and scope tightly.
- Secret stores: rotate values in AWS Secrets Manager and GCP Secret Manager that were accessed during the window.
4) Audit logs for exploitation
- AWS CloudTrail (examples):
aws cloudtrail lookup-events –lookup-attributes AttributeKey=EventName,AttributeValue=ListSecrets
aws cloudtrail lookup-events –lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue
- GCP Audit Logs:
gcloud logging read ‘resource.type=secretmanager.googleapis.com’ –limit=200
gcloud logging read ‘protoPayload.methodName=google.iam.admin.v1.CreateServiceAccountKey’ –limit=50
5) Network containment
- Block outbound to webhook.site at your egress controls and proxy. Search historical logs for requests to the exact exfil URL.
DevSecOps guardrails that actually change outcomes
This campaign rode on two realities: trust in maintainer updates and permissive publish paths. You can blunt both.
Package intake discipline for npm
- Adopt a cooldown: delay brand-new package versions by 48–72h in pipelines. Most malicious releases get caught inside a day. StepSecurity’s Package Cooldown Check automates this gate. pnpm added a minimumReleaseAge setting for the same reason; similar features exist in Taze/NCU workflows.
- Artifact provenance: require provenance/SLSA attestations where available; block un-attested publishes in CI.
- Lockfile policy: single owner for dependency updates, reproducible builders, and a rule that no production deploy occurs within the same PR that bumps a critical transitive unless a security exception is signed.
Publisher and registry hygiene
- Publisher hardening: enforce hardware-backed 2FA for maintainer accounts; don’t reuse SSO providers or email factors; monitor for 2FA reset phish across corporate mail.
- Automated anomaly detection: watch for publishes that do not originate from your authorized CI/CD. Tools like StepSecurity Artifact Monitor or equivalent homegrown checks can flag “hand-pushed” packages.
GitHub Actions blast-radius controls
- Mandatory review for workflow changes (workflow file-path protections + CODEOWNERS).
- Untrusted code path: run npm install of untrusted branches on isolated runners with no org secrets; prefer job-level permissions: that default to read-all.
- Secret minimalism: removed or masked secrets by default; use OIDC with constrained audience/claims over long-lived PATs.
Build agent hardening
- Egress filters for runners; e.g., block webhook.site and similar pastebins.
- Read-only tokens where possible; ephemeral tokens everywhere else.
- Filesystem risk: developer laptops and CI hosts often hold .npmrc, .aws/credentials, and ~/.git-credentials. Treat them as secrets vaults; disk encryption and agent isolation aren’t “nice to have”.
How ASPM helps you get ahead of the next one
You can’t win this with scanners alone. You need continuous context:
- Unified risk view across code → pipeline → runtime
Map where each dependency lands, which pipelines can publish, what secrets live in those pipelines, and which apps inherit those risks. That’s ASPM territory: one backlog per team, dedupe by context, and focus remediation where reachability and blast radius intersect. - Reachability-aware dependency policy
If a trojanized library is unreachable at runtime, don’t halt a release; if it’s reachable in critical paths, raise the gate. Tie this to your SCA/SBOM and CI policy so the decision is automatic. - Provenance-based exceptions
Write the rule once: only allow npm publishes signed by your CI service account with attested provenance; quarantine everything else. When the next attack drops, your policy blocks it by default while you investigate. - Campaign-based remediation
Treat this like a campaign: remove backdoor workflow, rotate tokens, re-pin affected versions, sweep org repos. Track it in your vulnerability management backlog as a single supply chain incident with child tasks per team—this reduces fatigue versus spraying dozens of tickets.
Triage checklist for security and platform teams
- Inventory: generate a dependency SBOM and diff against the version list above.
- Resolve: pin to safe versions; rebuild containers and serverless layers.
- Pipelines: scan repos for .github/workflows/shai-hulud-workflow.yml; delete; force a clean commit that removes it; protect the workflows/ path.
- Secrets: rotate npm, GitHub, cloud, and third-party tokens; re-issue OIDC workloads.
- Forensics: search logs for webhook.site egress and CloudTrail/GCP Secret Manager access.
- Comms: notify impacted developers; share detox steps for local machines (remove backdoor workflow clones, clear caches, re-auth CLI tools).
- Policy: enable version cooldown and provenance gates in PR checks; require approvals for workflow changes.
Notes on maintainers and attribution
- The npm account scttcper (Scott Cooper) publishes many @ctrl/* libraries, including @ctrl/tinycolor. Treat any installs of recently published versions with care and verify the source timeline before unblocking.
- Initial alert: credits include Daniel dos Santos Pereira for flagging the suspicious @ctrl/tinycolor update; Socket and StepSecurity published deep dives and kept the package list current as the story evolved.
References and further reading
- StepSecurity: full technical breakdown, IoCs, remediation guidance for the bundle.js campaign.
- Socket Research: analysis of the tinycolor incident and Nx attack wave; lists affected versions and details on token validation, AI-assisted exfil in related incidents.
- The Hacker News: concise summary of the 40-package compromise with the fixed package list and exfil workflow details.
- npm maintainer profile (scttcper) for publisher context and recent publishes.
- Daniel Pereira for the initial alert
Final word: hold the line on package intake
Speed is the attacker’s ally here: release, wait for installs, drain secrets, and ride CI persistence. Slow them down. Bake cooldown, provenance, and workflow-path protections into your DevSecOps pipelines. Let your ASPM practice decide what gets blocked, what gets quarantined, and what needs a hotfix, based on reachability and blast radius.
Get on top of your code and container vulnerabilities with Phoenix Security Actionable ASPM
Organizations often face an overwhelming volume of security alerts, including false positives and duplicate vulnerabilities, which can distract from real threats. Traditional tools may overwhelm engineers with lengthy, misaligned lists that fail to reflect business objectives or the risk tolerance of product owners.
Phoenix Security offers a transformative solution through its Actionable Application Security Posture Management (ASPM), powered by AI-based Contextual Quantitative analysis. This innovative approach correlates runtime data with code analysis to deliver a single, prioritized list of vulnerabilities. This list is tailored to the specific needs of engineering teams and aligns with executive goals, reducing noise and focusing efforts on the most critical issues. Why do people talk about Phoenix
• Automated Triage: Phoenix streamlines the triage process using a customizable 4D risk formula, ensuring critical vulnerabilities are addressed promptly by the right teams.
• Contextual Deduplication: Utilizing canary token-based traceability, Phoenix accurately deduplicates and tracks vulnerabilities within application code and deployment environments, allowing teams to concentrate on genuine threats.
• Actionable Threat Intelligence: Phoenix provides real-time insights into vulnerabilities’ exploitability, combining runtime threat intelligence with application security data for precise risk mitigation.
By leveraging Phoenix Security, you not only unravel the potential threats but also take a significant stride in vulnerability management, ensuring your application security remains up to date and focuses on the key vulnerabilities.
Get in control of your Application Security posture and Vulnerability management
Get on top of your code and container vulnerabilities with Phoenix Security Actionable ASPM powered by AI-based Reachability Analysis
Organizations often face an overwhelming volume of security alerts, including false positives and duplicate vulnerabilities, which can distract from real threats. Traditional tools may overwhelm engineers with lengthy, misaligned lists that fail to reflect business objectives or the risk tolerance of product owners.
Phoenix Security offers a transformative solution through its Actionable Application Security Posture Management (ASPM), powered by AI-based Contextual Quantitative analysis. This innovative approach correlates runtime data with code analysis to deliver a single, prioritized list of vulnerabilities. This list is tailored to the specific needs of engineering teams and aligns with executive goals, reducing noise and focusing efforts on the most critical issues.
Why do people talk about Phoenix?
• Automated Triage: Phoenix streamlines the triage process using a customizable 4D risk formula, ensuring critical vulnerabilities are addressed promptly by the right teams.
• Contextual Deduplication with reachability analysis: Utilizing canary token-based traceability for network reachability and static and dynamic runtime reachability, Phoenix accurately deduplicates and tracks vulnerabilities within application code and deployment environments, allowing teams to concentrate on genuine threats.
• Actionable Threat Intelligence: Phoenix provides real-time insights into vulnerabilities’ exploitability, combining runtime threat intelligence with application security data for precise risk mitigation.
By leveraging Phoenix Security, you not only unravel the potential threats but also take a significant stride in vulnerability management, ensuring your application security remains up to date and focuses on the key vulnerabilities.