Multi-ecosystem security scanner for the developer's machine and tools.
Covers source repos, developer machines, zero cloud calls except for osv.dev and NVD API.
UBEL is a software composition analysis (SCA) tool and install-blocking firewall built for teams who care about what enters their supply chain at every layer. Unlike report-only scanners, UBEL enforces policy — if a scan fails, it blocks the operation and tells you exactly why.
It spans the entire delivery chain: from the moment a developer adds a dependency, through CI validation, to what is running on a deployment server or inside an AI agent's runtime environment.
- Full dependency resolution with PURL generation
- Vulnerability scanning via batched API queries to OSV.dev and NVD's APIs
- Concurrent vulnerability enrichment (CVSS, fix recommendations, references)
- Policy engine — block/allow by severity threshold and unknown-severity packages
- Malicious package (infection) detection — always blocked regardless of policy
- Dependency graph with introduced-by and parent tracking
- Automatic report generation: timestamped JSON (
*.json) + HTML (*.html) + SBOM (*.cdx.json) + SARIF (*.sarif.json) per scan, pluslatest.*convenience links - Zero external runtime dependencies (Node.js stdlib only)
- Complete compliant, and enriched SBOM Cyclonedx V1.6 files with full dependencies and vulnerabilities data in VEX
- Complete compliant, and enriched SARIF v2.1.0 files
- Reachability analysis — each vulnerability is annotated with a reachability level (
total/high/medium/low) derived from package type, scope, dependency depth, attack vector, and import-scan confirmation across all supported ecosystems
| Command | Shortcut (Win/Linux) | Shortcut (Mac) | What it scans |
|---|---|---|---|
| UBEL: Scan Project | Ctrl+Alt+U |
Cmd+Alt+U |
All ecosystems inside the open workspace folder |
| UBEL: Scan Code Editor's Extensions | Cmd+Alt+X |
npm packages inside ~/.vscode/extensions or ~/.vscode-oss/extensions or ~/.cursor/extensions |
|
| UBEL: Scan Host Platform | Ctrl+Alt+P |
Cmd+Alt+P |
System software installed on this machine |
All three commands are also accessible via the Command Palette (Ctrl+Shift+P / Cmd+Shift+P) — search UBEL.
From the Marketplace
Search for UBEL in the VS Code Extensions panel, or install directly:
ext install Arcane-Spark.ubel-vscode
From VSIX
- Download
ubel-vscode-extension.vsixfrom the releases page. - Open the Command Palette → Extensions: Install from VSIX…
- Select the downloaded file.
Scans every ecosystem present anywhere inside the currently open workspace folder. Monorepos with mixed stacks are fully covered in a single pass — no configuration needed.
What gets scanned
| Ecosystem | Resolved From |
|---|---|
| Node.js (npm, pnpm, yarn, bun) | node_modules/ on-disk walk |
| Python | .venv/, venv/, virtual environment directories |
| PHP | vendor/ |
| Rust | Cargo.lock |
| Go | go.sum |
| C#/.NET | packages.lock.json, obj/project.assets.json |
| Java | pom.xml resolved dependencies |
| Ruby | Gemfile.lock |
Report location
<project-root>/.ubel/reports/latest.*
Scans the npm packages bundled inside your installed VS Code / Cursor / VS Codium extensions (~/.vscode/extensions or ~/.vscode-oss/extensions or ~/.cursor/extensions). Extensions are a meaningful supply-chain surface — they run with full Node.js access in the editor host process and are updated silently.
Report location
~/.vscode/extensions/.ubel/reports/latest.*
or
~/.vscode-oss/extensions/.ubel/reports/latest.*
or
~/.cursor/extensions/.ubel/reports/latest.*
Audits the system-level software installed on the developer's machine itself — a distinct attack surface from project dependencies. Vulnerabilities are matched using CPE 2.3 identifiers against the CVE/NVD database.
This catches what dependency scanners miss: a vulnerable version of Git, an unpatched Python interpreter, an outdated Docker Desktop install, or an end-of-life .NET runtime.
Windows — detected via registry probes and PowerShell, no elevated privileges required:
| Category | Components |
|---|---|
| Operating system | Windows 10 / 11 (build-accurate CPE version) |
| Security | Windows Defender |
| Runtimes | Node.js, Python, PHP, Go, Rust, Ruby, JRE, JDK |
| .NET | All installed .NET Core / Desktop / ASP.NET runtimes (multi-version) |
| Browsers | Chrome, Firefox, Microsoft Edge |
| Developer tools | Git, Docker Desktop, VS Code, Cursor |
| Shell | PowerShell |
Linux — reads the system package database directly, works as a standard user on most distributions:
| Distro family | Source |
|---|---|
| Debian / Ubuntu | /var/lib/dpkg/status |
| Alpine | /lib/apk/db/installed |
| Red Hat / AlmaLinux / Rocky | rpm -qa |
On RPM-based systems,
rpm -qamay return partial results depending on SELinux policy if run without elevated privileges.
Report location
The report is always written to ~/.ubel/reports/latest.*, independent of any open workspace.
~/.ubel/reports/latest.*
Every scan ends with a VS Code notification:
| Result | Notification | Meaning |
|---|---|---|
| ✅ | Scan complete — no policy violations | All packages passed |
| Policy violation | Vulnerable or malicious package found above threshold | |
| ❌ | Scan error | Unexpected failure — message contains details |
Every notification includes an Open Report button that opens the full interactive HTML report in your browser.
Each scan produces a self-contained HTML file that works fully offline. It contains six tabs:
| Tab | Contents |
|---|---|
| Dashboard | Vulnerability counts by severity, policy decision summary, scan metadata |
| Vulnerabilities | Full list of matched CVEs with CVSS score, EPSS, severity, fix version, reachability level, and policy decision |
| Inventory | Every scanned package with version, PURL, CPE, ecosystem, and vulnerability count |
| Graph | Interactive force-directed dependency graph — colour-coded by vulnerability status, with search, filter, drag, and pin |
| Stats | Severity distribution charts, top vulnerable packages, ecosystem breakdown |
| System | OS metadata, Node.js version, scan engine info |
Every vulnerability in the report is annotated with a reachability assessment. The analyzer operates on the existing report fields — package type, scope, dependency depth, CVSS attack vector, and the dependency graph — and performs a source-level import scan over the workspace files to confirm or refute whether the vulnerable package is actually used by application code.
The goal is prioritization: to separate vulnerabilities in packages your code actively exercises from those in packages that are installed but unreachable from any production code path.
Signals are evaluated in strict priority order. The first matching rule wins.
| Priority | Signal | Reachability | Confidence |
|---|---|---|---|
| 0a | Vuln ID starts with MAL- |
total |
high |
| 0b | Package scope includes env |
total |
high |
| 1 | Package type is non-library (app, framework, plugin, OS package, …) | total |
high |
| 2 | Scope is dev or test |
unreachable |
high |
| 3 | Import scan: package imported in source files | high or medium |
high |
| 4a | Import scan: direct import absent, but importing parent found | medium or low |
medium |
| 4b | Import scan: no direct or parent import found | unreachable |
medium |
| 5 | Orphan tool (no dependents in graph, no import scan available) | unreachable |
medium |
| 6 | Depth + attack vector heuristics | medium or low |
low |
Priority 0a (MAL-) — Malware advisories represent active supply-chain infections. The vulnerable code is the infection vector; reachability is unconditional regardless of how or whether the package is imported.
Priority 0b (env scope) — Packages carrying the env scope are part of the execution environment itself — OS packages, system libraries, runtimes, container-layer components. They are not imported by application code; they are the environment. Reachability is unconditional.
Priority 1 (non-library type) — Frameworks, applications, plugins, and OS-level packages have no meaningful import boundary. The component itself is the attack surface.
Priority 2 (dev/test scope) — Packages that are exclusively development or test dependencies are excluded from production runtimes.
Priorities 3–4 (import scan) — UBEL scans workspace source files for import statements matching the package. For transitive dependencies where the package itself is not directly imported, it checks whether any of the package's parents in the dependency graph are imported — confirming that the transitive path is exercised.
Priority 5 (orphan tool) — Root packages with no dependents and no import scan result are most likely standalone CLI tools not called by application code.
Priority 6 (heuristics) — When no higher-priority signal is available, depth in the dependency tree and the CVSS attack vector are used as weak proxies.
| Ecosystem | Extensions | Patterns matched |
|---|---|---|
| Node.js | .js .ts .mjs .cjs .jsx .tsx |
require('<pkg>'), from '<pkg>' |
| Python | .py |
import <pkg>, from <pkg> |
| Java / Kotlin | .java .kt .groovy .scala |
import <group>.<artifact> |
| C# / .NET | .cs .vb .fs |
using <Namespace> |
| PHP | .php |
use <Vendor>\\, require '<pkg>' |
| Go | .go |
"<module-path>" |
| Rust | .rs |
use <crate>::, extern crate <crate> |
| Ruby | .rb |
require '<gem>' |
Reachability results appear in the Vulnerabilities tab of the HTML report and in the machine-readable JSON report under each vulnerability's reachability field.
All package managers share the same policy engine. Policy is stored per-project in .ubel/local/policy/config.json.
| Field | Values | Default | Behaviour |
|---|---|---|---|
severity_threshold |
low medium high critical none |
high |
Block packages at or above this severity |
block_unknown_vulnerabilities |
true false |
true |
Block packages with CVEs but no CVSS score |
Infections (MAL-*) |
— | always blocked | Cannot be toggled; unconditionally blocked |
The threshold is inclusive — high blocks both high and critical. Setting none disables severity blocking but infections are still blocked.
| Surface |
|---|
| Source repos & monorepos |
| Developer machines (Windows / Linux) |
| VS Code extension |
UBEL walks the entire directory tree and detects all supported ecosystems in a single pass — no per-language configuration needed. Monorepos with mixed stacks (e.g. a Node.js frontend, Python backend, and Rust service in the same repo) are fully covered in one invocation.
The VS Code extension (Ctrl+Alt+P) and the ubel-platform CLI binary scan the host machine: OS, installed runtimes, browsers, developer tools, and security software. Vulnerabilities are matched using CPE 2.3 identifiers against the CVE/NVD database.
This surface catches what dependency scanners miss — a vulnerable version of Git, an unpatched Python interpreter, or an outdated Docker Desktop install.
Detected via registry probes and PowerShell — no elevated privileges required.
| Category | Components |
|---|---|
| Operating system | Windows 10 / 11 (build-accurate CPE version) |
| Security | Windows Defender |
| Runtimes | Node.js, Python, PHP, Go, Rust, Ruby, JRE, JDK |
| .NET | All installed .NET Core / Desktop / ASP.NET runtimes (multi-version) |
| Browsers | Chrome, Firefox, Microsoft Edge |
| Developer tools | Git, Docker Desktop, VS Code, Cursor |
| Shell | PowerShell |
Detected by reading the system package database directly.
| Distro family | Package manager | Source |
|---|---|---|
| Debian / Ubuntu | dpkg | /var/lib/dpkg/status |
| Alpine | apk | /lib/apk/db/installed |
| Red Hat / AlmaLinux / Rocky | rpm | rpm -qa |
On RPM-based systems,
rpm -qamay return partial results depending on SELinux policy if run without elevated privileges.
| Ecosystem | Package Manager | Resolved From |
|---|---|---|
| Node.js | npm, pnpm, yarn, bun | node_modules/ (on-disk walk) |
| Python | pip / virtualenv | .venv, venv, virtual environment directories |
| PHP | Composer | vendor/ |
| Rust | Cargo | Cargo.lock |
| Go | Go Modules | go.sum |
| C#/.NET | NuGet | packages.lock.json / obj/project.assets.json |
| Java/Kotlin | Maven | pom.xml resolved dependencies |
| Ruby | Bundler | Gemfile.lock |
Every scan writes a self-contained interactive HTML + JSON + SBOM + SARIF reports.
| Scan target | Report path |
|---|---|
| Workspace | <project-root>/.ubel/reports/latest* |
| VS Code / VS Codium / Cursor extensions | ~/.vscode/extensions/.ubel/reports/latest* or ~/.vscode-oss/extensions/.ubel/reports/latest* or ~/.cursor/extensions/.ubel/reports/latest* |
| Host platform | ~/.ubel/reports/latest* |
Previous scans are retained under:
<project-root>/.ubel/local/reports/npm/health/<year>/<month>/<day>/~/.vscode/extensions/.ubel/local/reports/npm/health/<year>/<month>/<day>/~/.vscode-oss/extensions/.ubel/local/reports/npm/health/<year>/<month>/<day>/~/.cursor/extensions/.ubel/local/reports/npm/health/<year>/<month>/<day>/~/.ubel/local/reports/npm/health/<year>/<month>/<day>/
- Node.js
>=18.0.0 - VS Code
^1.85.0(extension only)
UBEL is fully local. The only external call is to osv.dev's public API and NVD's API, which receives package PURLs (package name + version) to check for known vulnerabilities. No file contents, no dependency graphs, no machine identifiers, and no telemetry are sent anywhere.
AGPL-3.0-only — free for scanning your own projects and systems.
See LICENSE.md for details or contact [email protected] for commercial licensing.