mlab security
Scan your lockfiles for known CVEs from inside VS Code, on demand, powered by
mlab. Parsing and vulnerability resolution happen
entirely server side: the extension only uploads the lockfile you pick and shows
the result. No local database, no heavy dependencies.
Consent first, then automatic
Nothing is uploaded until you agree, once. The first scan opens a dialog that
explains exactly what is sent and asks for confirmation, and no network call
happens when the extension activates.
After you have agreed, mlab.autoScan (on by default) rescans a lockfile when
its contents change. Two things keep that cheap and predictable:
- Results are cached per file content, so an unchanged lockfile is never
re-uploaded. A
npm install that does not move any version costs nothing.
A cached result is trusted for 7 days, after which the lockfile is rescanned so
a newly published advisory is eventually seen, and is dropped from storage
after 30 days so the cache cannot grow without bound.
- Writes are debounced, so a burst of edits to the same lockfile produces one
scan, not several.
If you prefer the fully manual behaviour, set mlab.autoScan to false on the
mlab page or in your settings. With it off there is no file watcher at all.
How to scan
Any of these, and nothing else, starts a scan:
- Right-click a lockfile in the Explorer and choose Check for lock
vulnerabilities. This is the primary path.
- Right-click inside the editor when the active file is a recognized
lockfile, same menu entry.
- Command Palette:
mlab: Check for lock vulnerabilities,
mlab: Scan all lockfiles in workspace, mlab: Clear results,
mlab: Set API token, mlab: Manage API token & quota.
- The Rescan button in the results view.
The context-menu entry only appears on recognized lockfiles, never on other
files.
Right-clicking a file named, for example, Cargo.lock or package-lock.json
adds a single Check for lock vulnerabilities item to the Explorer context
menu, grouped with the other workspace actions. Right-clicking any other file
(for instance README.md or main.rs) shows no mlab entry at all. Selecting the
item opens a report panel beside the file: first an animated "Scanning ..." state
with a Cancel button, then the final report.
What you get
- Exploitation intelligence on every finding: the EPSS probability and
whether the CVE is in the CISA or EU known-exploited catalogues. This is what
makes triage possible: a critical at 0.02% EPSS and not exploited anywhere is
not the same emergency as a high that CISA lists as under active attack. The
report sorts by that, not by CVSS band alone.
- Analyze selection: highlight a URL, IP, email, file hash, MAC address or
domain,
right-click, and get it looked up. What the value is gets worked out on your
machine, so only the value itself is sent, and only to the endpoint for that
type. Works without a key at a reduced quota. Set
mlab.analyzeSelection to
false to remove the menu entry. Every result carries a See the full scan on
mlab link. One caveat worth knowing: a domain is the only kind that contacts
the target rather than reading a database. It reuses an existing report when
there is one, and only spends one of your 25 daily organisation-wide scans when
there is genuinely nothing to reuse.
- Hover any CVE identifier, in any file, for its CVSS, EPSS, known-exploited
status, risk score and weaknesses. Set
mlab.cveHover to false to turn it
off.
- A report panel beside the lockfile with a per-severity summary
(for example
3 critical, 12 high, 4 low across 6 packages) and a table of
findings: package, advisory (CVE id linking to its
vuln.mlab.sh page), the version it was fixed in, and a
short summary.
- A progress state that is genuinely cancellable: cancelling aborts the in-flight
HTTP request.
- Lockfiles with known vulnerabilities are colored in the Explorer by their
worst severity (red for high or critical, orange for medium, blue for low or
unknown), with a badge for that severity. The mark is driven by the content-keyed cache, so
it stays until the lockfile is actually patched.
- Diagnostics in the Problems panel, one per finding, anchored on the line of
the lockfile that declares the package.
mlab.severityFloor decides how they
read: at or above the floor, critical and high are Errors, medium is a Warning
and low or unknown is Information; below it, findings are downgraded to
Information. Nothing ever fails.
- See vuln report opens the last result for a lockfile straight from the
cache, without any network call and without spending a scan. It is on the
Explorer and editor context menus, and it is what clicking a lockfile in the
findings tree does. The report says how old a cached result is.
- An mlab entry in the Activity Bar holding the findings tree, grouped
lockfile -> severity -> advisory, with a badge showing the total finding count.
Clicking a lockfile opens it; clicking an advisory opens its CVE page.
- A full width mlab page (
mlab: Open mlab, or the home button in the view
title bar) with your quota status, the API token, the scan entry points and a
jump to the native settings editor. The Activity Bar icon can only ever open a
sidebar, so results live there and everything else lives on this page.
Supported lockfiles
Cargo.lock, package-lock.json, npm-shrinkwrap.json, yarn.lock,
pnpm-lock.yaml, composer.lock, Gemfile.lock, go.sum, requirements.txt,
poetry.lock, uv.lock, pdm.lock, Pipfile.lock, pom.xml,
gradle.lockfile, packages.lock.json, pubspec.lock, mix.lock, mise.lock,
and CycloneDX SBOMs named bom.json or bom.xml (an SBOM component without a
purl is matched by its CPE).
Adding a format is a one line edit: append it to LOCKFILES in
src/detect.ts, then run npm run sync:manifest. The menu
clauses, the activation event, the globs and the welcome text all derive from
that array, and CI fails if they drift.
Scan all lockfiles in workspace walks the workspace with workspace.findFiles
and skips node_modules, vendor, target, dist, and .git. Lockfiles
already in the cache cost nothing, and before uploading anything it tells you how
many files actually need a fresh scan and asks. Files are scanned one at a time,
waiting out the server's cooldown between them. The run shows progress, can be
cancelled, and stops early if the server keeps refusing scans rather than
burning the remaining files on the same error.
API token and quotas
|
Packages per scan |
Request size |
Cooldown between scans |
| Anonymous (per IP) |
512 |
4 MiB |
10 s |
| Free account, with a token |
1024 |
8 MiB |
5 s |
| Paid plan, with a token |
4096 |
32 MiB |
none |
A token also attaches the scans to your history on vuln.mlab.sh.
- Generate a token at vuln.mlab.sh/me/tokens.
- Run
mlab: Manage API token & quota (or mlab: Set API token) and paste it.
The token is stored only in VS Code
SecretStorage.
It is never written to your settings, to the workspace, or to disk in plaintext.
Background and batch scans wait out the cooldown (HTTP 429) and retry once. An
explicit scan shows the server's message (how long to wait, what the next tier
unlocks) and keeps your previous results. A file over the size limit (HTTP 413)
is reported the same way.
Privacy
- Only the lockfile you choose to scan is uploaded to
vuln.mlab.sh. Your source
code is never sent.
- Nothing is uploaded until you explicitly trigger a scan, and the first scan
asks for confirmation.
- The extension declares support for
Workspace Trust:
in Restricted Mode, scanning is disabled with a clear message.
- What happens to uploaded data is governed by the
mlab privacy policy.
Settings
Settings resolve through five layers, highest priority first:
<workspace>/.mlab/vuln.yml, a hand written override for this workspace
(flat key: value lines, never written by the extension)
<workspace>/.mlab/config.json, meant to be committed so a team shares one
configuration
~/.mlab/config.json, personal and applying to every workspace
- VS Code settings under
mlab.*, which is what earlier versions used and which
keeps working
- built in defaults
.mlab/vuln.yml
Run mlab: Create .mlab/vuln.yml for this workspace to get a commented
template. The same file is read by the
GitHub Action, so one file drives
the editor and CI.
# Turn mlab off in this workspace: no scans, no hovers, no lookups. Previous
# results are hidden, not deleted, and come back when the line is removed.
# disable: true
# Advisories accepted as known risk, hidden everywhere (and never failing CI).
ignoreVulns:
- CVE-2024-0000 # not reachable: only used in tests
autoScan: false
Ignored advisories are matched against the advisory id and all of its aliases,
and are filtered when results are shown, not when they are cached: editing the
list applies at once, without a rescan.
Every config file is checked when it is read. An unknown key (autoscan) or a
bad value (severityFloor: hgih) is reported in a warning and ignored rather
than applied silently. Settings set in vuln.yml are locked on the mlab page.
The mlab page shows which layer each value came from and lets you edit it, and
the native settings editor stays one click away.
| Setting |
Default |
Description |
mlab.autoScan |
true |
Rescan a lockfile when its contents change. Never uploads anything before you have consented once. |
mlab.ignoreGitIgnored |
true |
Skip lockfiles that git ignores in the workspace sweep and automatic rescans. An explicit check still scans the file. |
mlab.ignoreVulns |
[] |
Advisory ids (CVE-..., GHSA-...) accepted as known risk and hidden everywhere. Best kept in .mlab/vuln.yml with a comment saying why. |
mlab.analyzeSelection |
true |
Offer Analyze selection in the editor context menu. |
mlab.platformUrl |
https://mlab.sh/api/v1 |
Platform API base, for indicator lookups. |
mlab.cveHover |
true |
Show CVSS, EPSS and known-exploited status when you hover a CVE identifier. Only the identifier is looked up. |
mlab.apiUrl |
https://vuln.mlab.sh/api/v2/scan |
Scan endpoint. Override for a self-hosted instance. |
mlab.severityFloor |
any |
Lowest severity reported as a Warning/Error diagnostic; below it, findings are shown as Information. Tunes severity mapping only, never fails anything. |
mlab.timeoutMs |
30000 |
Per-request timeout in milliseconds. |
Notes and limits
- A manifest with more packages than your tier scans is cut at that limit; the
report says how many were left out, that they are not counted as clean,
and what the next tier allows.
- Entries the server cannot turn into a package coordinate (a git or path
dependency, an unpinned requirement, an SBOM component with neither purl nor
CPE) are listed as not scanned.
- Coordinates the scanner could not resolve (an upstream outage) are surfaced and
are not counted as clean.
- Timeouts, unreachable DNS, and non-JSON responses produce a readable
notification; full detail goes to the
mlab output channel.
Development
npm install
npm run build # bundle src -> dist/extension.js (esbuild)
npm run watch # rebuild on change
npm run typecheck
npm run lint
npm run test # unit tests
npm run package # produce a .vsix
npm run sync:manifest # regenerate the package.json parts derived from src/detect.ts
Press F5 to launch an Extension Development Host on test/fixtures. It runs
npm: watch, so sources rebuild on change with sourcemaps; press Cmd+R in that
window to reload the extension. Useful commands from its Command Palette:
Developer: Reload Window, Developer: Show Running Extensions, and
Developer: Open Webview Developer Tools to inspect the report and home panels
(webview code runs in its own context, so the Node debugger cannot see it).
Compatible editors
Any editor that runs VS Code extensions with API 1.85 or later.
From the Visual Studio Marketplace:
- Visual Studio Code (Stable and Insiders)
- GitHub Codespaces
- VS Code Remote (SSH, WSL, Dev Containers) and VS Code Server / Tunnels
From Open VSX:
- VSCodium
- Cursor
- Windsurf
- Kiro
- Google Antigravity
- Firebase Studio
- Void
- Positron
- code-server
- Gitpod / Ona
- Eclipse Theia and Theia IDE
- Eclipse Che / Red Hat OpenShift Dev Spaces
In the browser, on vscode.dev and github.dev:
everything works except the personal ~/.mlab/config.json layer, since a
browser has no home directory. Settings saved with the User scope go to the
VS Code user settings there instead.
Data sources & disclaimer
Use of the extension and of the mlab API is subject to the
mlab terms of service and
privacy policy.
Vulnerability data is aggregated by vuln.mlab.sh from third party sources and
shown here as received:
All information is provided for informational purposes only, as is, without
warranty of accuracy or completeness. A scan with no findings does not mean a
project has no vulnerabilities.
License
MIT