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 marked red in the Explorer, with a
badge for the worst 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 and the rest are
Warnings; 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, composer.lock,
Gemfile.lock, go.sum, requirements.txt, mise.lock.
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. It is quota
aware: lockfiles already in the cache cost nothing, and before spending anything
it tells you how many files actually need a fresh scan and asks. The run shows
progress, can be cancelled, and stops early if the hourly quota runs out rather
than burning the remaining files on the same error.
API token and quotas
Anonymous scans are limited to 8 per hour per IP. A personal API token raises
this to 25 per hour.
- 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.
When an anonymous scan is rate limited (HTTP 429), the extension keeps your
previous results and offers to open the token page or add a token.
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.
Settings
Settings resolve through four layers, highest priority first:
<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
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.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
- Manifests over 512 packages are scanned up to that ceiling; the report
shows a visible warning.
- 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).
License
MIT