Your first scan
This page picks up right after Install vulkro-sf and gets you findings on a real Salesforce codebase in under a minute. You end up with a first set of findings: severity counts in the terminal, plus an optional SARIF / JSON / HTML file for a code-review tool or CI gate.
What you need
vulkro-sf scans Salesforce source on disk. The first scan needs no live org;
the org connector is optional and covered in
Live-org setup.
Point the scanner at one of these:
- An SFDX project: a directory with
sfdx-project.jsonat the root and aforce-app/(or similar) source tree underneath. - A retrieved metadata folder: the output of
sf project retrieve start --target-org ...or a legacy MDAPIpackage.xmlretrieval. - Any directory containing Apex (
.cls,.trigger), LWC (.js,.html), Aura (.cmp), Visualforce (.page,.component), Flow (.flow-meta.xml), or Salesforce metadata XML.
A typical SFDX layout looks like this:
my-package/
sfdx-project.json
force-app/
main/
default/
classes/
lwc/
flows/
objects/
profiles/
...
The scanner walks the project root, finds the Salesforce files, and runs the detectors against them.
The first command
vulkro-sf scan ./force-app
That is the whole command. Point it at the project root or the force-app/
directory; both work. The scanner auto-detects the project shape.
What you see
The default output is plain text grouped by severity. A finished scan prints a summary line, then the findings:
Vulkro for Salesforce 0.5.2
Scanning ./force-app ...
Findings: 12 (Critical: 1, High: 4, Medium: 6, Low: 1)
[CRITICAL] sf_metadata::auth_provider_hardcoded_consumer_secret
force-app/main/default/authProviders/Slack.authprovider-meta.xml:14
Hardcoded consumerSecret in metadata. Move to Protected Custom
Metadata or External Credential.
[HIGH] apex_crud_fls::missing_fls_on_dml
force-app/main/default/classes/LeadController.cls:42
DML insert without CRUD/FLS enforcement. Use
Database.insert(record, AccessLevel.USER_MODE) or
insert as user record;
...
Each finding carries:
- A severity label (Critical, High, Medium, Low).
- A rule ID in the form
module::check_name. Pass it tovulkro-sf explain <id>for the long-form rationale (sources, fix, AppExchange-checklist mapping). - A file path and line number.
- A short message stating the problem and the recommended fix.
Exit codes
vulkro-sf scan follows the standard Vulkro exit-code contract:
0: scan completed and no findings were reported.1: scan completed and findings were reported. Wire CI to fail the build on1.2: error (bad arguments, IO failure, project not detected, internal crash). The message on stderr says what to fix.
In a CI gate the common pattern is vulkro-sf scan ./force-app || exit $?: any
non-zero code halts the build, and 1 versus 2 lets later steps tell findings
apart from infrastructure problems.
Choosing an output format
The --format flag picks the output shape:
vulkro-sf scan ./force-app --format text # default
vulkro-sf scan ./force-app --format sarif -o findings.sarif
vulkro-sf scan ./force-app --format json -o findings.json
vulkro-sf scan ./force-app --format html -o findings.html
- text (default): scannable terminal output, grouped by severity.
- sarif: SARIF 2.1.0. Upload to GitHub Code Scanning, GitLab Vulnerability Report, or any SARIF-aware tool. The format every downstream pipeline understands.
- json: Vulkro-native JSON with every field the scanner produces (confidence score, OWASP mapping, AppExchange section, breach-class label). Use it when SARIF would flatten that detail.
- html: a self-contained single-file report. Open it in any browser to share with a non-technical reviewer.
Use -o <file> to write to a file. Without -o, the output goes to stdout,
ready to pipe into another tool.
Tightening (or loosening) what fires
Confidence threshold
Every finding carries a confidence score. --min-confidence filters anything
below the threshold:
vulkro-sf scan ./force-app --min-confidence high # high only
vulkro-sf scan ./force-app --min-confidence medium # high + medium (default)
vulkro-sf scan ./force-app --min-confidence low # everything
On a new codebase, start strict (high) to surface the obvious findings without
noise, then walk the threshold down as you fix things.
Category filter
--category narrows the scan to one of the five pillars:
vulkro-sf scan ./force-app --category code # Apex / LWC / Aura / VF / Flow
vulkro-sf scan ./force-app --category posture # SecuritySettings / sharing
vulkro-sf scan ./force-app --category identity # Profiles / PermSets
vulkro-sf scan ./force-app --category thirdparty # Connected Apps / Named Credentials
vulkro-sf scan ./force-app --category ai # Agentforce / GenAI
Pass the flag more than once to combine pillars:
vulkro-sf scan ./force-app --category code --category identity
With no --category flag, the scan runs every pillar. A narrowed scan is faster
and fits when one workstream owns one pillar (for example, a security review
focused on guest-user exposure runs with --category identity).
Where to go next
- Methodology: the master reference for what a safe Salesforce app should be and how every Vulkro detector traces back to a published standard.
- AppExchange readiness report: turn the same findings into the Security Review pre-submission HTML artifact.
- Live-org setup: connect to a live org via
the
sfCLI to enable the posture and packages detectors. - CI/CD integration: wire
vulkro-sf scaninto GitHub Actions, GitLab CI, or Bitbucket Pipelines.