DEV Community

Cover image for Your VS Code Extensions Are a Supply Chain Attack Surface
GDS K S
GDS K S

Posted on

Your VS Code Extensions Are a Supply Chain Attack Surface

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       │
└───────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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?
Enter fullscreen mode Exit fullscreen mode

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                             │
└──────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

3. Kill auto-updates

// settings.json
{
  "extensions.autoUpdate": false,
  "extensions.autoCheckUpdates": false
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
# 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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   │
└───────────────────────┘          └───────────────────────┘
Enter fullscreen mode Exit fullscreen mode

VS Code's extension model was built in 2015 when the threat model was different. We need:

  1. Permission scoping. Extensions should declare exactly what files and APIs they access. A JSON formatter should not touch your terminal.

  2. Sandboxing. Extensions should run in isolated processes. Browser extensions already work this way. It's solvable.

  3. 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   │
│                                                   │
└──────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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)