Last week a VS Code extension called specstudio.code-wakatime-activity-tracker was caught dropping a Zig-compiled binary onto developer machines. It looked like WakaTime. It tracked your activity alright, just not in the way you expected.
This is part of a campaign researchers are calling GlassWorm. And it's not the first incident. It won't be the last.
I went through my own extensions after reading about it. I had 47 installed. I could confidently vouch for maybe 20 of them. The rest? I installed them months ago, never checked who published them, never looked at what permissions they had. I'm guessing your situation is similar.
What your editor can actually access
Before we get into the attack, look at this. This is what VS Code (and every extension running inside it) has access to:
┌─────────────────────────────────────────────────┐
│ VS Code │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Extension│ │ Extension│ │ Extension │ │
│ │ Theme │ │ Formatter│ │ "WakaTime" │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ SAME PERMISSION LEVEL │ │
│ │ No sandbox. No isolation. Full access. │ │
│ └──────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
├───────────────────────────────────────────────────┤
│ ~/.ssh/* ~/.env ~/.aws/ │
│ ~/.gitconfig Terminal Source code │
│ API keys DB creds Git tokens │
└───────────────────────────────────────────────────┘
There is no sandbox. A color theme extension has the same system access as a full debugger. The marketplace review process catches obvious malware but it's not a security audit. Extensions with 50,000 installs have been caught doing shady things.
How GlassWorm works
Here's the kill chain. Each step is designed to avoid detection:
Step 1: INSTALL
User installs "code-wakatime-activity-tracker"
Looks legit: decent reviews, familiar branding
│
▼
Step 2: DROP
Extension downloads a Zig-compiled binary
(Zig = not in most antivirus signature DBs)
│
▼
Step 3: PERSIST
Binary registers as a background process
Survives VS Code closing
│
▼
Step 4: HARVEST
Scans for:
├── .env, .env.local, .env.production
├── *.pem, *.key (SSL/SSH keys)
├── .git/config (remote URLs → company ID)
└── ~/.aws/credentials
│
▼
Step 5: EXFILTRATE
Sends harvested data to C2 server
Encrypted, looks like normal HTTPS traffic
│
▼
Step 6: (WORST CASE) INJECT
Receives instructions to modify source files
Could inject backdoors into YOUR commits
That last step is the one that should keep you up at night. It's not just stealing secrets. It could be modifying your code before you push it. Your CI passes. Your review looks clean. The backdoor was there before you committed.
The audit: my results
I scored each of my 47 extensions on a simple trust matrix:
VERIFIED PUBLISHER
Yes No
┌─────────────┬──────────────┐
Yes │ KEEP │ INSPECT │
OPEN SOURCE │ (20 exts) │ (4 exts) │
├─────────────┼──────────────┤
No │ INSPECT │ REMOVE │
│ (7 exts) │ (16 exts) │
└─────────────┴──────────────┘
Result: 47 → 31 extensions
Removed: 16 | Flagged for inspection: 11
The 16 I removed fell into three buckets:
- Duplicates of built-in VS Code features (VS Code has gotten better, some extensions are unnecessary now)
- Extensions I installed for a specific project months ago and never used again
- Extensions from unverified publishers with no source code
Step-by-step: audit yours in 30 minutes
1. Dump your extension list
code --list-extensions > my-extensions.txt
wc -l my-extensions.txt # how many do you have?
2. Run the trust check
For each extension, run it through this:
Extension: _______________
┌──────────────────────────────────────────┐
│ Verified publisher? [ ] Y [ ] N │
│ Open source / GitHub link? [ ] Y [ ] N │
│ Updated in last 6 months? [ ] Y [ ] N │
│ Install/rating ratio normal? [ ] Y [ ] N │
│ Do I actually use this? [ ] Y [ ] N │
├──────────────────────────────────────────┤
│ 5/5 = KEEP │
│ 3-4 = INSPECT (check source, permissions)│
│ 0-2 = REMOVE │
└──────────────────────────────────────────┘
3. Kill auto-updates
// settings.json
{
"extensions.autoUpdate": false,
"extensions.autoCheckUpdates": false
}
This is the single most impactful change. A legitimate extension can be compromised through a malicious update pushed to the marketplace. If auto-update is on, that update is on your machine before you hear about it.
4. Set up a credential file watcher
# macOS - alerts you if anything touches sensitive files
# Save as ~/watch-creds.sh and add to login items
#!/bin/bash
WATCH_PATHS="$HOME/.ssh $HOME/.aws $HOME/.env"
fswatch -r $WATCH_PATHS \
--event Created \
--event Updated \
--event Renamed |
while read file; do
osascript -e \
"display notification \"$file\" with title \"Credential File Touched\""
echo "$(date): $file" >> ~/credential-access.log
done
# Linux equivalent using inotifywait
inotifywait -m -r ~/.ssh ~/.aws -e modify -e create |
while read dir event file; do
notify-send "Credential Alert" "$dir$file was $event"
done
Not bulletproof. A sophisticated attacker works around file watchers. But most attacks are unsophisticated, and this catches those.
What I kept (and why)
| Extension | Publisher | Open Source | Trust Signal |
|---|---|---|---|
| ESLint | Microsoft | Yes | Microsoft-published, millions of installs |
| Prettier | Prettier | Yes | Core team maintains it |
| GitLens | GitKraken | Yes | Verified company, public security policy |
| Error Lens | usernamehw | Yes | I've read the source, it's small |
| Tailwind IntelliSense | Tailwind Labs | Yes | First-party from the Tailwind team |
| Thunder Client | Ranga Vadhineni | Partial | Verified publisher, 5+ year track record |
The pattern:
TRUST = verified_publisher + open_source + active_maintenance + real_identity
If any of those four is missing, you need a good reason to keep it.
VS Code vs browser extensions: the gap
Here's what bothers me. Chrome figured this out years ago.
Browser Extensions (Chrome) VS Code Extensions
┌───────────────────────┐ ┌───────────────────────┐
│ Declares permissions │ │ Full system access │
│ upfront ("tabs", │ │ by default. No │
│ "storage", etc.) │ │ permission manifest. │
│ │ │ │
│ Runs in sandboxed │ │ Runs in Node.js with │
│ process │ │ your user permissions │
│ │ │ │
│ Limited API surface │ │ Can spawn processes, │
│ │ │ read any file, open │
│ │ │ network connections │
│ │ │ │
│ Reviewed + signed │ │ Basic automated scan │
└───────────────────────┘ └───────────────────────┘
VS Code's extension model was built in 2015 when the threat model was different. We need:
Permission scoping. Extensions should declare exactly what files and APIs they access. A JSON formatter should not touch your terminal.
Sandboxing. Extensions should run in isolated processes. Browser extensions already work this way. It's solvable.
Code signing. Require publishers to sign their code. Make it auditable.
Until those things happen, the responsibility is on us.
Quick reference card
Save this somewhere:
┌──────────────────────────────────────────────────┐
│ VS CODE EXTENSION SECURITY CHEAT SHEET │
├──────────────────────────────────────────────────┤
│ │
│ BEFORE INSTALLING │
│ ☐ Check publisher verification (blue checkmark) │
│ ☐ Check GitHub repo link exists │
│ ☐ Check last update date (< 6 months) │
│ ☐ Read recent reviews for red flags │
│ │
│ AFTER INSTALLING │
│ ☐ Disable auto-update (settings.json) │
│ ☐ Review changelogs before manual updates │
│ ☐ Set up credential file monitoring │
│ │
│ QUARTERLY │
│ ☐ Run: code --list-extensions | wc -l │
│ ☐ Remove unused extensions │
│ ☐ Re-check publisher status on remaining ones │
│ │
│ RED FLAGS │
│ ✗ No source code link │
│ ✗ Publisher name doesn't match extension name │
│ ✗ Thousands of installs but < 10 ratings │
│ ✗ Recently transferred to new publisher │
│ ✗ Requests network access for offline-only task │
│ │
└──────────────────────────────────────────────────┘
Gagan Deep Singh builds open source tools at Glincker. Currently working on profClaw (AI agent engine) and AskVerdict (multi-model AI verdicts).
If this was useful, follow me on Dev.to or X where I post weekly.
Top comments (0)