Skip to main content

Changelog

Release notes for every Vulkro version

Plain-language release notes for Vulkro for Salesforce and Vulkro Core, newest first. Read one product or both together.

Release artifacts on dist.vulkro.com ship with SHA256SUMS and a CycloneDX SBOM.

Both products: 61 releases, newest first.

Added

  • Next.js 16 proxy.ts is read as middleware. Next.js 16 renamed Middleware to Proxy. A proxy.ts (or .js, .tsx, .mjs) at the project root or under src/ now counts for route entry points and for the check that flags routes protected only by a middleware matcher. A proxy.ts elsewhere, such as lib/proxy.ts, stays an ordinary module.

  • MCP list_rules lists the whole rule catalogue, not only the rules with a detector page.

  • OWASP-LLM02 is accepted as a name for the sensitive-information disclosure rule. SARIF keeps OWASP-LLM06.

Changed

  • "Proven" means one thing everywhere. A finding is proven when its evidence holds a data-flow step from untrusted input, a missing sanitizer on that flow, a guard check that found the guard absent, or a pattern that is conclusive on its own in C, C++ or PHP. A trace made only of related context is no longer called proven. The disposition field in JSON, the editor, the finding card, MCP prove, verify_sarif and the gates all use this one rule.
  • Fewer Criticals, each with proof behind it. A finding the proof gate holds at Medium or High is no longer raised back by a later step. When that happens the finding says so in its confidence note, for example "the risk model rates it Critical, held by the proof gate at High". Expect a noticeably shorter Critical list on the same code.
  • A missing guard can be the proof. For missing authentication, a record read without an ownership check, and a role change without a role check, the guard check's own verdict (guard absent or inadequate) now counts as proof for that finding, so these can be rated Critical again.

Fixed

  • ctx check tells apart same-named methods of two classes in one file. Changing InvoiceRepo.findById no longer flags calls to userRepo.findById(id) when both classes are declared in the same file, including an imported instance such as export const userRepo = new UserRepo().

  • ctx check explains its problem count when it differs from the numbered items below it, for example 2 problems (2 in 1 numbered item below).

  • HIPAA compliance output lists each control once. vulkro compliance --profile hipaa printed five controls twice and gave two controls another control's guidance text. Each control now has one row with its own text, and the control ids in JSON are the bare ids (for example 164.312(b)).

  • Rule links open the current documentation at docs.vulkro.com, in the editor, SARIF and pull-request annotations.

  • Help text matches the binary. fix --dry-run states the exit code it returns (1 when a fix would apply), and triage documents its local model default.

  • HIPAA rows. 164.312(e)(1) and 164.312(e)(2)(ii) now each have their own text, and 164.312(a)(2)(iv) its own remediation. The 0.35.3 note said every control already had its own text; these two still shared theirs.

  • Unanalysed languages are named as unchecked. The scan warning for a language the engine does not analyse now says plainly that no security check ran on those files.

  • Help text says where AI is used. vulkro --help states that detection uses no AI and lists the opt-in commands that call a model.

  • The Claude Code plugin text matches its behaviour. It no longer claims to run in offline mode.

Corrections to earlier notes

  • 0.32.0: the "same issues with fewer tokens" result was measured on apps used while developing Vulkro, which flatters it.
  • 0.33.0: "flagged all 10 edits that left the build broken" comes from one Go repository, and the check was tuned on those same replays.

Added

  • disposition on every finding in vulkro-sf scan --format json (admitted, demoted or not examined), the same field the core scanner's JSON carries.
  • attack_graph.paths[].weakest: the weakest proof grade among a path's steps. paths[].proof keeps its meaning (the strongest step), which is not the path's confidence.

Changed

  • "Proven" means one thing everywhere. A finding is proven only when its evidence holds a data-flow step from untrusted input, a missing sanitizer on that flow, or a check that is conclusive on its own. A trace made only of related context is no longer called proven, and a guest user's access to a class is reach, not proof.
  • Fewer Criticals, each with proof behind it. A finding the proof gate holds at Medium or High is no longer raised back by the Salesforce risk model; the finding's confidence note says when that happened.
  • Every Critical is explained. An attack path explains a Critical finding when it reaches data and its weakness step sits on the finding's own line. A proven data flow is also explained when the Salesforce risk model placed it on a chain from an actor through an entry point to sensitive data; the model's chain alone, without that proof, no longer makes anything Critical. summary.critical_on_path counts only the Criticals a graph path explains.

Fixed

  • --gate-vs reports only what the change introduced. Gating a scan against a branch or commit, for example vulkro-sf scan ./force-app --gate-vs origin/main, reported every existing finding as new on a tree with no changes and failed the build. Findings are now matched across the two trees by their path in the project.

  • Rule links in the editor open the current documentation at docs.vulkro.com.

  • Stable test-debt finding ids. QD-TEST ids no longer change between runs of the same code.

  • The MCP sf_scan_project tool returns the same JSON as vulkro-sf scan --format json.

  • Help text for org mfa, event monitoring and scan --org matches what the commands do: scan --org reads no business records.

  • No example threat intel in findings. Earlier releases shipped example data that read as real intel: managed-package advisories with CVE numbers that do not exist, Salesforce Trust incidents that never happened, an AppExchange catalogue with made-up advisories and review dates, an end-of-life entry for Marketing Cloud Connect, and placeholder OAuth client IDs. That data is gone. vulkro-sf sca no longer reports SF-SCA-001 or SF-SCA-002 from it, org trust-status no longer reports SF-TRUST-001 from it, and org packages --verify no longer reports SF-PKG-VERIFY findings from it.

  • "Not checked" instead of a clean result. Where no intel data ships, the command or console view now says the check did not run: vulkro-sf sca prints a "Not checked" line, org trust-status links your instance on status.salesforce.com, org connected-apps --check-compromised says the check did not run, and the Intel views in the console and in Vulkro Cloud say "No intel data loaded". You can still load your own vetted lists from a local file.

  • Compliance coverage. Four controls that relied on those checks (DORA Art. 9(4)(f), ISO 27001 A.5.21 and A.8.8, NIS2 Art. 21(2)(d)) are now rated Partial.

Corrections to earlier notes

  • "A Critical finding is always explained by a path from a person to your data" was not true in earlier releases: some Criticals sat on no path, some with no proof at all. From 0.28.0 every Critical is either on a path to data or a proven data flow the risk model places on one (see Changed).
  • "A proven path from an unauthenticated guest to sensitive data is Critical": earlier releases counted a guest's class access as proof. From 0.28.0 the path needs proof of the data flow as well.

See what the latest release finds in your code and your orgs.