Skip to main content

VS Code security extension (also Cursor and Windsurf)

Vulkro ships a Language Server Protocol server, exposed as the vulkro lsp subcommand of the main binary, and a VS Code extension that consumes it. The same extension loads in Cursor and Windsurf (both VS Code forks).

There are two extensions, and they install side by side: Vulkro (this page, driven by vulkro) and Vulkro for Salesforce (driven by vulkro-sf). Each takes its own files. Anything under a folder containing sfdx-project.json goes to the Salesforce extension, including the JavaScript and HTML inside lwc/ and aura/; everything else goes to this one. Installing only Vulkro in a Salesforce project does not scan Apex: it shows a one-time notice pointing at the other extension. Each has its own Marketplace listing, README and icon. See the Salesforce extension page.

The extension surfaces Vulkro findings inside your editor as diagnostics, with hover-to-explain, quick-fix code actions, report export, a CI-parity check, and optional AI assistance. AI assistance is advisory and local: it never changes a deterministic scan result, and the published benchmark is AI-free.

Install

The extension spawns the vulkro binary you already have, so install the scanner first (see the install guide).

Install Vulkro from the Visual Studio Marketplace (search for Vulkro in the Extensions view), or from the CLI you already have, which finds your editor even when its code command is not on your PATH:

vulkro install-extension # detects your editor, asks, then installs
vulkro-sf install-extension # the Vulkro for Salesforce extension

It detects VS Code, Cursor, Windsurf, and VSCodium (on your PATH and in each editor's standard install location), downloads the .vsix from the Vulkro CDN, and installs it through the editor's own CLI. Flags: --yes (skip the prompt), --editor <name>, --vsix <file> (install a local package). VULKRO_VSIX_URL overrides the download URL for a self-hosted mirror or an air-gapped copy. If no editor is found, it prints how to add the code command or install from a VSIX by hand.

Build from source / install a .vsix manually. You can also build and install the package directly, from integrations/editors/vscode:

cd integrations/editors/vscode
npm install
npm run package:editions

That emits vulkro-<version>.vsix (Vulkro) and vulkro-sf-<version>.vsix (Vulkro for Salesforce). Install one through your editor: Extensions view, ... menu, Install from VSIX.

If the binary cannot be found when the extension starts, it offers an Install action (also the Vulkro: Install or update the scanner binary command) that downloads the right release for your platform, verifies its .sha256, and installs it into ~/.vulkro/bin. That download runs only when you trigger it, never on activation; it respects VULKRO_OFFLINE=1 and honours the VULKRO_CDN host override.

Free, Pro and signing in

No account is needed. Every language scans without signing in, and every finding comes with its proof and its fix. That is Free, on one repository at a time, and it never expires.

Signing in holds Pro. In the editor that means the views that turn one scan into a picture of the whole application: attack paths, impact, working-tree review, the data-flow and code-structure maps, history, trends, compare, the evidence formats, the executive report and the AI impact narrative. Each Pro view opens three times on Free before it locks, so you can see what it adds on your own code; the lock line names the capability and its See pricing action opens the pricing page. The first verified device login on an account starts a 14-day term of the full product.

The extension is a thin layer over the CLI: the vulkro binary owns your licence, so signing in from the editor runs the same device login as vulkro login.

  1. Command Palette (Cmd/Ctrl+Shift+P) -> Vulkro: Sign in (or the Sign in button in the Vulkro sidebar's Account view).
  2. Your browser opens to your account; approve the device code the editor shows.
  3. The editor is bound to your account. If you had already run vulkro login on this machine, you are signed in immediately - the extension and the CLI share the same on-disk license.

Sign out with Vulkro: Sign out. Air-gapped machines use Vulkro: Activate license file to activate a .lic offline instead. Licenses are issued directly by our team (license@vulkro.com).

What you get

  • Diagnostics on open and save. Open any Python, JavaScript, TypeScript, JSX/TSX, Go, or Java file inside a project with a root marker (.git, package.json, pyproject.toml, Cargo.toml, go.mod, pom.xml, build.gradle, build.gradle.kts, composer.json, sfdx-project.json, or vulkro.toml). The server paints the open file first with a fast single-file scan, then reconciles with a full project scan moments later. Saving re-runs the engine; typing only republishes cached results (debounced), so keystrokes never trigger a re-scan.
  • Scanning without an account. Every language, including Java, scans without signing in, with the proof and the fix on every finding. Signing in holds Pro; the first verified device login on a device starts a 14-day term of the full product. Licences are issued directly by our team (license@vulkro.com).
  • Salesforce projects belong to the other extension. Anything under a folder containing sfdx-project.json, the JavaScript and HTML inside lwc/ and aura/ included, is scanned by Vulkro for Salesforce, which installs side by side with this one. Without it, this extension shows a one-time notice pointing at it and leaves those files alone. See the Salesforce extension page.
  • Hover to explain. Hovering a diagnostic surfaces the rule id, severity, message, and remediation in a Markdown popup.
  • Quick fixes on the lightbulb. Every Vulkro diagnostic offers Suppress (insert a // vulkro:disable next-line <rule> comment) and Explain (the rule's long-form explainer). A small set of clear-cut patterns (weak hash, yaml.load, cookie flags, debug flags, and similar) also gets a deterministic one-line fix; each template refuses to edit any line whose shape it does not fully recognise. Fix with AI (review) appears when local AI is set up (see below).
  • Sidebar views. The Vulkro activity-bar container shows Overview, This File, Issues, and Account by default. Turning on vulkro.showAdvancedViews reveals Changes, History, Impact, Codemap, Trends, Dependencies, AI Hunt, Suppressions, and Ask Vulkro. Changes, History, Impact, Codemap and Trends are Pro views, with three free looks each. A status bar item shows the live finding count.
  • Watch mode. vulkro.watch (or Vulkro: Toggle watch mode) rescans the whole workspace as files change on disk, including files you have not opened and changes made by git checkout or codegen. Off by default.
  • Baseline. Set, clear, or toggle a baseline to hide known findings and surface only new ones.
  • Severity display floor. vulkro.severityThreshold hides findings below the chosen level from the gutter, the Problems panel, and the Vulkro views. It is a display floor, not a scan setting: the scanner still detects everything.

You stay in control of edits

The language server never writes to your files. Every edit it can produce (the suppression comment, a deterministic one-line fix, an AI fix candidate) is proposed through the editor and applied only when you accept it. AI fix candidates go one step further: a candidate is only offered after a fresh deterministic re-scan of the patched working copy confirms the finding no longer appears and the file still parses. That is what "verified" means here; it does not claim the build compiles or the tests pass.

Export a report

Vulkro: Export report (SARIF and other formats) (vulkro.exportReport) runs the same whole-project vulkro scan that CI would, captures the output, and saves it where you choose:

  • SARIF 2.1.0 (the portable default): open it in a SARIF viewer or upload it to your code-scanning platform.
  • JSON: the native Vulkro findings document, for scripts and jq.
  • HTML is offered only when the installed engine's scan accepts --format html; the command probes scan -h so the picker never offers a format your binary would reject.

A scan that exits 0 (clean) or 1 (findings reported) both produce a report; only exit 2 (error) is treated as a failure.

Editor / CI parity

Vulkro: Verify editor / CI parity (vulkro.verifyCiParity) runs the CI-equivalent scan (vulkro scan <root> --format json), counts findings by severity, and reports how your vulkro.severityThreshold display floor maps onto a CI invocation. It then offers to copy the matching command, for example:

vulkro scan . --min-severity low

--min-severity is the CLI twin of the editor's display floor: it drops findings below the level from the output (composing with --fail-on, which then evaluates the filtered set), so CI and the editor agree on what appears. See CLI: scan.

AI assistance (local first)

All AI features are optional and advisory: they never change a deterministic scan result, and the benchmark stays AI-free. The default transport is a local model through Ollama, default model qwen2.5-coder:7b, so nothing leaves your machine.

  • Vulkro: Set up AI model lists recommended models (with their licenses), pulls your pick, and self-tests the connection. Test AI connection and Disable AI manage it afterwards.
  • Fix issue with AI (review + apply) and Fix all issues with AI draft fixes for findings, validate each one with a deterministic re-scan (a fix is verified when the re-scan no longer reports the finding and the file still parses; the build compiling or tests passing is not claimed), show you the diff, and apply only what you accept.
  • Explain impact with AI, Review my changes with AI, AI Hunt, and the Ask Vulkro chat view build on the same local model.

Using your editor's AI model instead

If you do not run Ollama, vulkro.ai.transport: "editor" (or Vulkro: Use editor AI model) reuses the model your editor already provides (for example GitHub Copilot) through a loopback shim on 127.0.0.1. This is opt-in behind an explicit confirmation, because prompt content (which can include your source code and findings) is sent to whatever provider backs that model, usually a cloud service. It is refused outright when VULKRO_OFFLINE=1 is set. Vulkro: Use local AI model switches back.

Your editor's AI agent can call Vulkro

On hosts new enough to expose the APIs (the extension targets VS Code 1.101+; older hosts degrade gracefully), the extension also plugs the scanner into the editor's own AI agent:

  • Language-model tools. vulkro_scan_file scans a single file and returns its findings; vulkro_explain_finding explains a rule id. Agent mode can call both, and you can reference them in prompts (#vulkroScanFile, #vulkroExplainFinding). The Vulkro for Salesforce extension registers vulkro_sf_* twins, so both co-exist in one host.
  • MCP server. An MCP server-definition provider teaches the editor to launch the engine's own stdio MCP server (vulkro mcp serve) with VULKRO_OFFLINE=1 set, so the agent's MCP scans never reach the network.

Settings

SettingDefaultPurpose
vulkro.pathvulkroPath to the vulkro binary, or the bare name if it is on PATH. The extension spawns <path> lsp.
vulkro.severityThresholdlowLowest severity shown (critical, high, medium, low, info). A display floor: match it to your CI --min-severity.
vulkro.showAdvancedViewsfalseReveal the full set of sidebar views beyond Overview, This File, Issues, and Account.
vulkro.watchfalseRescan the whole workspace as files change on disk, including unopened files.
vulkro.lsp.debounceMs300Debounce window (ms) for didChange republishes, clamped to [50, 5000]. Passed as VULKRO_LSP_DEBOUNCE_MS.
vulkro.ai.model(empty)Override the local AI model; empty uses the engine default (qwen2.5-coder:7b). Passed as VULKRO_AI_MODEL.
vulkro.ai.url(empty)Base URL of the local Ollama (OpenAI-compatible) endpoint; empty uses http://127.0.0.1:11434/v1. Passed as VULKRO_AI_URL.
vulkro.ai.transportlocallocal keeps AI fully on-machine; editor reuses the editor's model through the loopback shim (opt-in, see above).
vulkro.trace.serveroffTrace LSP traffic in the Vulkro output channel.

The Vulkro for Salesforce extension has its own settings namespace (vulkro-sf.path, vulkro-sf.severityThreshold, vulkro-sf.scanOnSave, vulkro-sf.watch, vulkro-sf.targetOrg, vulkro-sf.trace.server); see the Salesforce extension page.

Because the server maps Critical and High to the same editor severity (Error), the critical and high thresholds behave identically in the editor.

How the LSP talks to the scanner

vulkro lsp runs the scan in-process: no subprocess, no JSON-over-pipe. It uses the same detection pipeline as vulkro scan (the full extractor set, the auth model, taint analysis, and the same suppression pass), so a // vulkro:disable directive silences the same finding in the editor and in CI. Diagnostics are pushed by the server per file. vulkro lsp exits 0 on a clean shutdown and 2 on an operational error; set VULKRO_LSP_LOG=1 for a stderr message trace.

Performance

Opening the first file in a project (and every save) publishes the current file's findings from a fast single-file scan first, so squiggles land in a fraction of a second, then a full project scan reconciles the complete picture. Typing republishes cached results only; the engine re-runs on save (or on any disk change when watch mode is on).

For a scoped terminal loop alongside the editor, run something like vulkro scan . --min-confidence high --scope src (see CLI: scan).

Suppressing network egress from inside the editor

To suppress all network egress from the binary the editor spawns, set:

// settings.json
"terminal.integrated.env.osx": {
"VULKRO_OFFLINE": "1"
}

(Adapt osx to linux / windows as needed.)

VULKRO_OFFLINE=1 is the single switch and covers everything: scans, the managed binary install, and the editor-AI transport (which is refused under it). The MCP server the extension registers is always launched with VULKRO_OFFLINE=1 regardless.

What this isn't (yet)

  • No standalone JetBrains plugin. The server works with any LSP-aware editor in principle; vulkro lsp --help prints ready-made snippets for Neovim (nvim-lspconfig), Helix, and Emacs eglot. VS Code (and its forks) is the only editor with a packaged extension today.
  • No unreviewed rewrites. Every edit, deterministic or AI-drafted, is applied only when you accept it, and AI candidates must first pass the deterministic re-scan described above.
  • No as-you-type engine runs. Diagnostics refresh from cache while you type; the engine re-runs on save (or on disk changes in watch mode).
  • vulkro scan: the CLI front door that produces the same findings the LSP surfaces, plus the --min-severity parity flag.
  • Salesforce extension page: the other extension, driven by the vulkro-sf server.
  • Pricing: which views are Free and which are Pro, in the scanner's own words.