TL;DR: Open VSX’s new pre-publish scanning pipeline suffered a fail-open flaw. Flood the publish endpoint, scanners skip entirely, and malicious extensions go live marked “PASSED.” Reported February 8, 2026; fixed in three days.
Open VSX (open-vsx.org), the go-to extension marketplace powering Cursor, Windsurf, and VS Code forks, launched a pre-publish scanning pipeline to combat rising threats. Think malware detection, secret scanning, binary analysis, and name-squatting: these are essential defenses for developers. But a subtle bug turned this safeguard into a wide-open door.
Launched via GitHub Issue #1331 and PR #1529, the system inspects every extension upload:
- Publisher submits via API; extension saves but stays inactive.
- Fast sync checks run inline failures and reject immediately.
- Background jobs parallelize full scanners (e.g., malware, secrets).
- Completion service waits for all to pass, then activates. Flags trigger admin quarantine.
- Watchdog recovers stuck jobs.
No extension hits users without clearance. Solid design until load breaks it. The flaw hid in ExtensionScanService.java. Its submitScannerJobs() method returns a single boolean: true If jobs are enqueued, false otherwise. But false meant two things:
- No scanners configured (safe; activate).
- Enqueue failed (unsafe; scanners exist but couldn’t start).
PublishExtensionVersionHandler.java assumed the safe case every time. Under load? Database pool exhausts, jobScheduler.enqueue() exceptions fly, enqueuedCount hits zero, boolean flips to false extension activates as “PASSED.” The recovery service had the same hole.
Imagine a bank vault: “No guards on duty” (okay) vs. “Guards tried but collapsed” (disaster). One Boolean couldn’t distinguish. Any free account works, no privileges needed.
Pack malicious .vsix payloads, flood publishes. Each hits the shared DB pool and JobRunr queue. Concurrency spikes, enqueues fail silently (logged, ignored). Gate opens; extensions blend in seamlessly, with no UI flags skipped scans.
Testing confirmed it: Controlled floods reliably bypassed. Production? Tight window per try, but zero-cost retries (no rate limits) make it inevitable. CWEs: 636 (Not Failing Securely), 755 (Exception Mishandling), 362 (Race), 400 (Resource Exhaustion).
Reported Sunday, February 8, 2026. Open VSX acknowledged the same day; fixed on February 11 via commit 64720, cc: explicit failure states, no ambiguous booleans. Professional response; kudos.
Risk window closed, but audit recent installs. Broader takeaway: Explicit failures beat fail-open anti-patterns. Distinguish “no work” from “work failed.”
This underscores marketplace pressures: One boolean flipped security on its head. Stay vigilant.
Disclosure Timeline:
- 2026-02-08: Reported.
- 2026-02-11: Acknowledged and fixed.
Site: cybersecuriytpath.com