Skip to main content

SARIF output

SARIF (Static Analysis Results Interchange Format) is the industry-standard machine-readable format for SAST findings. Vulkro for Salesforce emits SARIF 2.1.0 when invoked with --format sarif. Use it whenever the consumer is a code-scanning platform: GitHub Code Scanning, GitLab Security Dashboard, Azure DevOps Advanced Security, Sonatype, or a vendor-neutral SARIF viewer.

Generating

# Emit SARIF for the source pass.
vulkro-sf scan . --format sarif -o vulkro-sf.sarif

# Anti-patterns can also emit SARIF.
vulkro-sf antipatterns . --format sarif -o antipatterns.sarif

# Live-org perms / packages emit SARIF too.
vulkro-sf org perms --target-org my-prod --format sarif -o perms.sarif

Shape

Each Vulkro finding maps to one SARIF result with a ruleId, a level, a message, and one locations entry pointing at the file and line range. The full set of detectors that contributed to the scan is enumerated in tool.driver.rules, so a SARIF viewer can show the rule description alongside each finding without a separate lookup.

{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [
{
"tool": {
"driver": {
"name": "vulkro-sf",
"version": "0.5.2",
"informationUri": "https://vulkro.com/sf",
"rules": [
{
"id": "apex_soql_injection",
"name": "ApexSoqlInjection",
"shortDescription": {
"text": "SOQL string concatenation from a tainted source"
},
"helpUri": "https://vulkro.com/sf/docs/detectors/apex#soql-injection"
}
]
}
},
"results": [
{
"ruleId": "apex_soql_injection",
"level": "error",
"message": {
"text": "SOQL query is constructed by concatenating an untrusted string ('name'). Use bind variables: [SELECT Id FROM Lead WHERE Name = :name]."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "force-app/main/default/classes/LeadSearch.cls"
},
"region": {
"startLine": 42,
"endLine": 42,
"startColumn": 9,
"endColumn": 64
}
}
}
],
"partialFingerprints": {
"vulkroFindingHash/v1": "8a3f1c92"
},
"properties": {
"confidence": "high",
"category": "code",
"owasp": "API8:2023"
}
}
]
}
]
}

Fingerprint scheme

GitHub Code Scanning (and most other SARIF consumers) re-opens a "closed" alert as new whenever the location fingerprint changes. After a rebase, a file rename, or a whitespace tidy, that produces a wave of spurious "new findings" that bury the actual new ones.

Vulkro emits partialFingerprints.vulkroFindingHash/v1 for every result. The hash is computed from:

  • the rule ID,
  • the normalized file path (relative to the SFDX project root),
  • the normalized AST shape of the finding's enclosing function / method / Flow node (whitespace and comments stripped),
  • the rule-specific evidence tag (e.g. the tainted-identifier name for injection findings, the metadata-element name for posture findings).

The hash is intentionally independent of line numbers, so a finding that moves from line 42 to line 44 after a refactor keeps the same fingerprint and the existing alert stays linked. The hash IS sensitive to the AST shape, so a fix that rewrites the vulnerable construct invalidates the fingerprint and the alert closes cleanly.

Severity mapping

Vulkro severitySARIF level
Criticalerror
Higherror
Mediumwarning
Lownote
Infonote

GitHub Code Scanning treats error as a blocking finding by default; warning and note are surfaced but do not block by default.

Consumers

ConsumerNotes
GitHub Code ScanningUpload via github/codeql-action/upload-sarif or gh api. Uses partialFingerprints to keep alerts stable across runs.
GitLab Security DashboardUse the SAST report artefact type. GitLab converts SARIF into its native vulnerability shape.
Azure DevOps Advanced SecurityNative SARIF ingest via the Microsoft Security DevOps task.
VS Code SARIF Viewer (Microsoft)Open the .sarif file directly to navigate findings inline with the source.
sariftools (sarif-tools, multitool)CLI converters and diff helpers.