Module: SvgSentinel::Sarif

Defined in:
lib/svg_sentinel/sarif.rb

Overview

Builds a SARIF 2.1.0 log from scan results so findings drop straight into GitHub code scanning and other SARIF-aware tooling. Severity maps to SARIF level (critical -> error, warning -> warning); the element path becomes a logical location.

Constant Summary collapse

SCHEMA =
"https://json.schemastore.org/sarif-2.1.0.json"
INFORMATION_URI =
"https://github.com/msuliq/svg_sentinel"
LEVELS =
{critical: "error", warning: "warning"}.freeze

Class Method Summary collapse

Class Method Details

.document(entries) ⇒ Object

entries: an Array of [label, Result].



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/svg_sentinel/sarif.rb', line 19

def document(entries)
  results = []
  rules = {}

  entries.each do |label, result|
    result.findings.each do |finding|
      rules[finding.code] ||= rule_for(finding)
      results << result_for(label, finding)
    end
  end

  {
    "version" => "2.1.0",
    "$schema" => SCHEMA,
    "runs" => [
      {
        "tool" => {
          "driver" => {
            "name" => "svg_sentinel",
            "version" => SvgSentinel::VERSION,
            "informationUri" => INFORMATION_URI,
            "rules" => rules.values
          }
        },
        "results" => results
      }
    ]
  }
end

.message_text(finding) ⇒ Object



76
77
78
# File 'lib/svg_sentinel/sarif.rb', line 76

def message_text(finding)
  finding.detail ? "#{finding.message} (#{finding.detail})" : finding.message
end

.result_for(label, finding) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/svg_sentinel/sarif.rb', line 58

def result_for(label, finding)
  location = {
    "physicalLocation" => {
      "artifactLocation" => {"uri" => label}
    }
  }
  if finding.path && !finding.path.empty?
    location["logicalLocations"] = [{"fullyQualifiedName" => finding.path}]
  end

  {
    "ruleId" => finding.code.to_s,
    "level" => LEVELS.fetch(finding.severity, "note"),
    "message" => {"text" => message_text(finding)},
    "locations" => [location]
  }
end

.rule_for(finding) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/svg_sentinel/sarif.rb', line 49

def rule_for(finding)
  {
    "id" => finding.code.to_s,
    "name" => finding.code.to_s,
    "shortDescription" => {"text" => finding.message},
    "properties" => {"category" => finding.category.to_s}
  }
end