mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

Security

VSCan: What Scanning Malicious VSCode Extensions Reveals About Agent Tool Privilege Boundaries

VSCode extensions inherit full system access. So do agent tools. VSCan's detection heuristics expose the privilege boundary problem both ecosystems face.

Source: vscan.dev
VSCan: What Scanning Malicious VSCode Extensions Reveals About Agent Tool Privilege Boundaries

VSCode extensions run with full file system, network, and credential access. No sandbox. No capability manifest. No runtime enforcement. Dozens of malicious extensions have already shipped through the official marketplace, and the only defense most developers have is trust plus post-compromise detection.

This is the same privilege boundary problem agent tools face. When you invoke a tool (whether it’s a VSCode extension or an agent function), what stops it from doing anything the host process can do? VSCan is a free scanner built by a security researcher after personal exposure to this gap. The detection heuristics it uses expose the structural weaknesses in both ecosystems.

The Privilege Inheritance Problem

VSCode extensions inherit the full privilege set of the editor process:

  • File system: Read and write anywhere the user can touch
  • Network: Arbitrary outbound connections, no egress filtering
  • Credentials: Access to environment variables, SSH keys, cloud tokens
  • Process spawning: Shell out to any binary on the system
  • Extension API: Hook into editor events, modify code, intercept keystrokes

Agent tools operate under the same model. When an LLM calls a tool function, that function runs in the orchestrator’s execution context. If the orchestrator has database credentials, the tool can exfiltrate them. If it can shell out, the tool can pivot to the host OS. If it has network access, the tool can phone home.

The VSCode marketplace relies on pre-publication review and user reports. The agent tool ecosystem relies on developer audits and prompt-level guardrails. Neither has runtime containment.

How VSCan Detects Malicious Behavior

VSCan performs static analysis on extension source code after fetching it from the marketplace. The scanner looks for:

  • Obfuscated code patterns: Base64 blobs, eval chains, dynamic imports from external URLs
  • Suspicious API calls: child_process.exec, fs.readFile on known credential paths, https.request to non-CDN domains
  • Permission mismatches: Extensions requesting broad API access but implementing narrow functionality
  • Known malicious signatures: Hashes of previously identified payloads, domain reputation checks

The scanner does not execute the extension. It parses the JavaScript bundle, builds a call graph, and flags high-risk patterns. This is similar to how you might audit an agent tool before adding it to your orchestrator’s registry.

Example Detection Heuristic

// Simplified pattern VSCan might flag
const suspiciousPatterns = [
  {
    name: 'credential_exfiltration',
    check: (ast) => {
      const fileReads = findCalls(ast, 'fs.readFile');
      const networkCalls = findCalls(ast, 'https.request');
      const credPaths = ['.ssh', '.aws', '.kube', '.npmrc'];
      
      return fileReads.some(call => 
        credPaths.some(path => call.args.includes(path))
      ) && networkCalls.length > 0;
    },
    severity: 'critical'
  }
];

This heuristic is brittle. Obfuscation defeats it. Legitimate extensions that sync settings to a cloud service trigger false positives. But it surfaces the core issue: without runtime enforcement, you are auditing intent from static code.

What a Capability Manifest Would Look Like

The VSCode extension model has a package.json that declares requested permissions, but enforcement is weak. An extension can request workspace.fs and then read any file. There is no per-file allowlist, no egress domain restriction, no credential scope isolation.

A real capability manifest for agent tools would need:

CapabilityScopeEnforcement Layer
File systemPath prefix allowlistOS-level chroot or seccomp filter
NetworkDomain allowlist, no raw socketsFirewall rule or proxy intercept
CredentialsExplicit token grants, no env varsSecrets manager with ephemeral tokens
Process spawningBinary allowlist, no shellExec wrapper with syscall filtering
State mutationDeclared side effects onlyOrchestrator-level transaction log

VSCode does not enforce this. Most agent orchestrators do not either. The gap is not tooling. The gap is that both ecosystems prioritized developer velocity over containment, and now the installed base is too large to retrofit.

Why the Marketplace Model Fails

The VSCode marketplace has published over 50,000 extensions. Microsoft reviews new submissions, but the review is shallow. Malicious extensions slip through by:

  • Delayed activation: Clean code at publication, malicious payload fetched after install
  • Typosquatting: Names that mimic popular extensions
  • Compromised publisher accounts: Legitimate extensions updated with malicious code

Agent tool registries face the same attack surface. A tool that starts benign can be updated to exfiltrate data. A tool with a similar name to a trusted one can be substituted via prompt injection. A tool that fetches its implementation from a remote URL can be backdoored post-deployment.

The marketplace model assumes trust is transitive. If the publisher is trusted and the initial review passes, the tool is safe forever. This does not hold.

Applying VSCan’s Approach to Agent Tools

You can adapt VSCan’s heuristics to agent tool validation:

  1. Static analysis of tool source: Parse the function body, flag obfuscation, check for network calls and file I/O
  2. Behavioral signatures: Log tool invocations, detect anomalies like credential file reads followed by HTTP POST
  3. Dependency auditing: Scan imported packages for known vulnerabilities or suspicious maintainers
  4. Runtime sandboxing: Execute tools in isolated containers with explicit capability grants

The last step is the only one that actually contains the blast radius. The first three are detective controls. They tell you a tool is risky, but they do not stop it from running.

Minimal Sandbox Sketch

import subprocess
import json

def invoke_tool_sandboxed(tool_name, args, allowed_paths, allowed_domains):
    """
    Run agent tool in a restricted container with explicit capabilities.
    """
    config = {
        'image': f'tool-runtime:{tool_name}',
        'network': 'none',  # Override with proxy if allowed_domains
        'volumes': [f'{p}:/mnt/{i}:ro' for i, p in enumerate(allowed_paths)],
        'env': {},  # No host env vars
        'cap_drop': ['ALL'],
        'security_opt': ['no-new-privileges']
    }
    
    if allowed_domains:
        config['network'] = 'proxy'
        config['env']['ALLOWED_DOMAINS'] = ','.join(allowed_domains)
    
    result = subprocess.run(
        ['docker', 'run', '--rm', json.dumps(config), tool_name] + args,
        capture_output=True,
        timeout=30
    )
    
    return result.stdout.decode()

This is not production-ready, but it shows the shape. The tool runs in a container with no network by default, read-only volume mounts for specific paths, and no access to host environment variables. If the tool needs network, it goes through a proxy that enforces the domain allowlist.

The Observability Gap

VSCan gives you a report after scanning. It does not give you runtime telemetry. You do not know if a flagged extension actually exfiltrated data, or if it was a false positive.

Agent orchestrators need the same observability for tools:

  • Invocation logs: Which tool was called, with what arguments, by which agent
  • Resource access logs: Files read, network connections opened, processes spawned
  • State mutation logs: Database writes, API calls, external side effects
  • Anomaly detection: Baseline normal behavior, flag deviations

Without this, you are flying blind. A malicious tool can run for weeks before you notice the damage.

Failure Modes

Both VSCode extensions and agent tools fail in predictable ways:

  • Privilege escalation: Tool exploits a vulnerability in the host runtime to break out of its intended scope
  • Data exfiltration: Tool reads credentials or sensitive files and sends them to an attacker-controlled server
  • Supply chain compromise: Tool dependency is backdoored, malicious code runs transitively
  • Prompt injection: Attacker crafts input that tricks the agent into invoking a malicious tool or misusing a legitimate one

The first three are containment failures. The last one is an orchestration failure. You need defenses at both layers.

Technical Verdict

Use VSCan if you install VSCode extensions from the marketplace and want a quick static analysis check before trusting them. It is free, requires no login, and surfaces obvious red flags.

Avoid relying on it as your only defense. Static analysis cannot catch delayed payloads, obfuscated code, or compromised updates. You need runtime containment.

For agent tools, adopt the same mindset. Audit tool source before adding it to your registry. Log every invocation. Run tools in sandboxes with explicit capability grants. Treat the tool boundary as a security perimeter, not a convenience abstraction.

The privilege inheritance model is broken in both ecosystems. The fix is not better scanning. The fix is enforcement at runtime.

Tags

agentic-ai orchestration infrastructure

Primary Source

vscan.dev ↗