The CanisterWorm Wake-Up Call
In March 2026, the CanisterWorm malware spread through compromised npm packages — and it exposed how blind most developers are to what is actually sitting in their node_modules.
Not just what packages are installed. But:
- How big is each one?
- Does it have known vulnerabilities?
- When was it last maintained?
That last one matters more than people think. A package that has not been touched in 2,000 days is not necessarily broken — but it is a higher-risk surface for supply chain attacks. Attackers look for abandoned packages with high download counts and weak maintainer security.
I wanted to see all three columns at once. I could not find a tool that did it. So I built one.
What node-weight shows
npx node-weight
That is it. Zero install. Run it in any Node.js project directory and you get a table:
┌─────────────────────────┬──────────┬──────────┬───────────────┐
│ Package │ Size │ Security │ Last Updated │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ commander │ 182.0 KB │ ✓ clean │ 683 days ago │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ signal-exit │ 75.2 KB │ ✓ clean │ 978 days ago │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ ora │ 68.2 KB │ ✓ clean │ 424 days ago │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ emoji-regex │ 47.1 KB │ ✓ clean │ 2584 days ago │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ cli-table3 │ 45.1 KB │ ✓ clean │ 689 days ago │
├─────────────────────────┼──────────┼──────────┼───────────────┤
│ chalk │ 43.3 KB │ ✓ clean │ 205 days ago │
└─────────────────────────┴──────────┴──────────┴───────────────┘
21 packages | 614.9 KB | 0 vulnerabilities
Every row shows:
- Size — actual disk footprint of the installed package files
-
Security — pulled from
npm auditin real-time (clean, or severity level) - Last Updated — days since the package was last published to npm
Why all three columns matter together
Most existing tools only give you one piece:
| Tool | Size | Security | Freshness |
|---|---|---|---|
| Bundlephobia | ✓ | ✗ | ✗ |
| npm audit | ✗ | ✓ | ✗ |
| depcheck | ✗ | ✗ | ✗ |
| node-weight | ✓ | ✓ | ✓ |
Bundlephobia is great but it shows bundle size (after treeshaking, browser context) — not installed disk size, and nothing about security or maintenance. npm audit tells you about CVEs but not which packages are bloating your build or which ones were last touched in 2019.
node-weight gives you the complete picture in one command.
When freshness becomes a red flag
A "2584 days ago" entry for emoji-regex looks alarming. But context matters: emoji-regex is a Unicode specification package that simply does not need updates. Its last update was intentional.
What would concern me is a package with:
- 1,000+ days since last update
- High weekly downloads across the ecosystem
- A single maintainer
That combination is the exact profile attackers look for when staging supply chain attacks. They wait for maintainer access to go dormant, then submit "helpful" PRs.
node-weight does not flag those patterns automatically — but it gives you the data to spot them yourself in 30 seconds.
How it works under the hood
node-weight does three things in parallel:
-
Disk scan — walks
node_modulesand sums file sizes per package -
npm audit — runs
npm audit --jsonand maps vulnerabilities back to package names - Registry batch — hits the npm registry API in batches to fetch last-publish dates
All three run concurrently, then results are merged into the table. On a project with 200 packages it typically completes in 5–8 seconds.
Try it on your project
# In any Node.js project:
npx node-weight
# Or on a specific path:
npx node-weight /path/to/your/project
No config files. No install step. Just run it.
→ npm: https://www.npmjs.com/package/node-weight
→ GitHub: https://github.com/hlteoh37/node-weight
Built as part of a public build-in-public experiment — shipping real tools, measuring real results. Follow the journey at profiterole-blog.
Top comments (0)