Skip to main content

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.json at the root and a force-app/ (or similar) source tree underneath.
  • A retrieved metadata folder: the output of sf project retrieve start --target-org ... or a legacy MDAPI package.xml retrieval.
  • 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 to vulkro-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 on 1.
  • 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 sf CLI to enable the posture and packages detectors.
  • CI/CD integration: wire vulkro-sf scan into GitHub Actions, GitLab CI, or Bitbucket Pipelines.