Skip to main content

VS Code, Cursor, and Windsurf extension

The Vulkro IDE extension publishes to the VS Code, Cursor, and Windsurf marketplaces from a single source tree. It wraps both binaries:

  • vulkro (the general-purpose scanner) for non-Salesforce workspaces.
  • vulkro-sf (the Salesforce-specific scanner) for SFDX projects.

Workspace auto-detection picks the right one. The rest of this page covers the SFDX side: installation, the binary-path override, per-file vs whole-workspace scans, inline findings in Salesforce file types, the "explain finding" hover, and the live-org command-palette integration.

Installation

Install from your IDE's marketplace; the extension ID is the same across all three:

IDEMarketplace
VS CodeMarketplace -> search Vulkro -> install
Cursorsame VS Code listing (Cursor consumes the VS Code marketplace by default)
Windsurfsame VS Code listing (Windsurf consumes the VS Code marketplace by default)

The extension is a thin shell over the CLI binaries: it does not re-implement detection logic. Findings come from vulkro or vulkro-sf exactly as the CLI emits them. Closed-source detectors stay closed-source; the extension is the UI surface, not a second implementation.

Workspace auto-detection

When you open a folder, the extension runs a short heuristic against the workspace root:

  1. sfdx-project.json present -> SFDX project, use vulkro-sf.
  2. force-app/ or src/ with *.cls, *.trigger, *.page, *.cmp, *.lwc content -> SFDX project, use vulkro-sf.
  3. Otherwise -> generic project, use vulkro.

In a multi-root workspace each root is classified independently; you can have an SFDX folder and a Node.js folder open in the same window and the extension picks the right binary per file.

The binary-path override

The extension expects vulkro and vulkro-sf on PATH. Override the location via VS Code settings if you installed to a custom directory:

// .vscode/settings.json (or User Settings)
{
// Path to the vulkro binary. Default: vulkro (resolved against PATH).
"vulkro.binaryPath": "/usr/local/bin/vulkro",

// Path to the vulkro-sf binary. Default: vulkro-sf (resolved against PATH).
"vulkro.sfBinaryPath": "/usr/local/bin/vulkro-sf",

// Minimum confidence level to surface findings. Mirrors the CLI flag.
// Default: medium
"vulkro.minConfidence": "high",

// Run on save (per-file scan) in addition to the on-demand command.
"vulkro.scanOnSave": true
}

The two binary-path settings are independent: you can run a custom vulkro-sf build (a local feature branch) while keeping the released vulkro for non-Salesforce folders. Useful for engineers iterating on the Salesforce module.

Per-file scan vs whole-workspace scan

The extension exposes both shapes through the command palette:

  • Vulkro: Scan current file -> runs the binary against the single file you are editing. Subsecond latency on the typical .cls file. The default keybinding is cmd+shift+v cmd+shift+f (macOS) or ctrl+shift+v ctrl+shift+f (other).
  • Vulkro: Scan workspace -> runs against the workspace root. Slower but reports the cross-file detections (multiple triggers per object, the ForcedLeak two-pass walk, the AppExchange-readiness rollup). Default keybinding cmd+shift+v cmd+shift+w.

Setting vulkro.scanOnSave: true runs the per-file scan automatically on save; that is the recommended shape during development. The workspace scan is the right thing to invoke before opening a pull request.

Inline findings

Findings render as VS Code diagnostics: red, yellow, or blue squiggles under the exact range, with the rule message in the hover and the finding in the Problems panel.

Every Salesforce-relevant file type carries inline findings:

  • Apex (.cls, .trigger) -> CRUD/FLS, sharing, SOQL injection, IDOR, mass-assignment, crypto, hardcoded secrets, System.debug of sensitive vars, anti-patterns (SOQL in loop, DML in loop, hardcoded IDs, etc.).
  • LWC (.js, .html, .css under lwc/) -> DOM XSS, postMessage missing origin, wire-to-innerHTML taint.
  • Aura (.cmp, .controller.js, .helper.js under aura/) -> aura:unescapedHtml with user input, Aura action CSRF.
  • Visualforce (.page, .component) -> escape="false" on user content, external <apex:includeScript> over HTTP, stack-trace disclosure, PageReference untrusted concatenation.
  • Flow XML (.flow-meta.xml) -> system-context DML, hardcoded record IDs, guest-context flows.
  • Profile XML (.profile-meta.xml) -> guest-user object exposure, over-privilege, viewAllRecords.
  • PermissionSet / PermissionSetGroup XML -> aggregation risk.
  • Metadata XML (.connectedApp-meta.xml, .namedCredential-meta.xml, .remoteSite-meta.xml, .corsWhitelistOrigin-meta.xml, .cspTrustedSite-meta.xml, .workflow-meta.xml, .securitySettings-meta.xml, etc.) -> posture findings.
  • GenAi metadata (.genAiFunction-meta.xml, .genAiPlanner-meta.xml, .genAiPromptTemplate-meta.xml) -> ForcedLeak class-bypass, agent surface findings.

The severity-to-squiggle-colour map matches VS Code defaults: Critical and High render as Error, Medium as Warning, Low as Information.

The "explain finding" hover

Hover any squiggle to see the rule ID, the one-line finding, the short remediation, and an Explain link. Clicking Explain opens a side-panel view rendered from vulkro-sf explain <RULE-ID>: the same long-form explanation the CLI emits, displayed without leaving the IDE.

The explain content covers:

  • What the rule looks for, in plain language.
  • The specific Salesforce safe-app standard it maps to (AppExchange Top-20 #N, PMD Apex rule X, Well-Architected dimension Y).
  • A safe pattern, with a code snippet.
  • The unsafe pattern, with a code snippet.
  • The 2025-26 breach class (if applicable) the rule defends against.

The same body is available at the CLI: vulkro-sf explain SF-AGENTFORCE-002 prints the identical text.

Salesforce CLI integration

The extension reads sf org list on startup and on the Vulkro: Refresh org list command. Authenticated orgs show up in the command palette under:

  • Vulkro: Live org status (pick org) -> vulkro-sf org status --target-org <alias>
  • Vulkro: Live org perms (pick org) -> vulkro-sf org perms --target-org <alias>
  • Vulkro: Live org packages (pick org) -> vulkro-sf org packages --target-org <alias>

The alias picker is the same list sf org list produces. The extension does not store the token, does not implement its own OAuth flow, and does not shell out to anything but sf for the credential side; see the sf CLI handoff for the full call shape.

If sf is not on PATH, the org commands grey out in the palette and the extension shows the install instruction for your platform.

Quiet-mode and the SARIF view

For users who prefer a once-per-PR rollup over inline squiggles:

  • Set vulkro.scanOnSave: false and rely on Vulkro: Scan workspace invoked manually before opening a PR.
  • Use Vulkro: Show SARIF report to open the most recent scan result as a single-pane SARIF view (the same file the CI pipeline uploads to GitHub Code Scanning / GitLab Security Dashboard).

The SARIF view groups findings by rule and severity, with click-to-jump into the source range. It is the right view for triaging the workspace scan before opening a pull request.

Where to go next

  • The sf CLI handoff: what happens when the extension fires a live-org command.
  • Methodology: the rule taxonomy the inline findings map to.
  • CI/CD integration: the matching pre-merge gate so IDE findings cannot ship through a PR uncaught.