vulkro-sf scan
Scans an SFDX project or retrieved metadata folder for security findings across Apex, LWC, Aura, Visualforce, Flow and metadata. The analysis runs on your machine: source, metadata and findings never leave it.
vulkro-sf scan ./force-app
vulkro-sf scan . --format sarif > vulkro-sf.sarif
vulkro-sf scan . --gate-vs origin/main # CI: fail only on new findings
A path inside an SFDX project widens to the project root, because the rest of the project is part of the same deployable unit. Use --subtree to scan exactly the path given. For live-org posture, use the vulkro-sf org commands.
Flags
| Flag | What it does |
|---|---|
[PATH] | SFDX project or retrieved metadata. Default .. |
--format <fmt> | table (default), json, sarif, ocsf (OCSF 1.3.0 events, one per line), or a pull-request format: github-annotations, gh-pr-inline, gh-pr, gitlab-mr, bitbucket-pr, azure-pr (pipe into your SCM, for example | gh pr comment -F -). |
--min-confidence <high|medium|low> | Lowest confidence to report. Default medium. Low-confidence findings stay out of the output and the exit code; SARIF keeps them as suppressed results. |
--gate-vs <ref> | Scan the project again at a git ref and exit 1 only on findings new since then. Also set by VULKRO_SF_GATE_BASE. |
--metadata-only | Scan metadata only, for folders or org snapshots with no Apex. |
--subtree | Scan exactly PATH, not the whole project. |
--no-suppress | Ignore // vulkro:disable annotations and report everything. Same as VULKRO_NO_SUPPRESS=1. |
--org <alias> | Read the live org (through your sf login) to grade attack paths by who really holds each grant. Findings are unchanged; paths are raised or lowered one severity step. |
--post-to <target> | After the scan, post a summary to slack=<url>, teams=<url>, jira=<KEY>, pagerduty or saved. Repeatable. Never changes the exit code. |
--include-pmd, --include-eslint, --include-retirejs | Also run that locally installed tool with a bundled security-only config and merge its findings. Off by default. |
--ai-explain | Add an advisory note on why each finding matters for the security review. See below. |
--ai-code-segregation | Report which findings landed on files marked as AI-generated, per tool. Marker-based; calls no model. |
Environment variables (detector switches, notification credentials, the rules bundle) are listed by vulkro-sf env scan.
Suppressing a finding
Put an annotation on or above the line (use <!-- ... --> in XML and HTML):
// vulkro:disable next-line <rule-id>
// vulkro:disable-line <rule-id>
// vulkro:disable-file <rule-id>
Run with --no-suppress in CI to see what the annotations hide.
AI notes (--ai-explain)
After the scan, the local model set up with vulkro-sf ai writes a plain-language note on why each candidate finding (CRUD and FLS, SOQL injection, sharing, Flow system mode, and findings with unknown reachability) matters for the AgentExchange (formerly AppExchange) Security Review.
--format jsonadds anai_advisoryobject to annotated findings.--format tableprints the notes to stderr; stdout is unchanged.- SARIF and the pull-request formats ignore the flag.
Findings, severities and the exit code never change. --ai-model and --ai-url override the model for one run; --no-ai turns it off. The flag is ignored with --gate-vs and --metadata-only.
Exit codes
| Code | Meaning |
|---|---|
0 | No findings at or above --min-confidence. |
1 | Findings reported, or no active trial or Pro (license_required). |
2 | Error. |
Inside a git hook, a machine without a licence is not refused: the hook prints one notice and lets the commit through.
See also: antipatterns, appexchange-report, SARIF output