29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/scanner.rb', line 29
def scan(repo)
findings = []
workflow_count = 0
if scan_github?
raw_workflows = @client.fetch_workflows(repo)
workflows = raw_workflows.map { |w|
Workflow.new(filename: w[:filename], content: w[:content])
}
workflow_count = workflows.length
dependabot = @client.fetch_dependabot_config(repo)
has_zizmor = workflows.any? { |w| w.filename.match?(/zizmor/i) }
has_dependabot_actions = dependabot_has_actions?(dependabot)
workflows.each do |wf|
next if wf.parse_error?
findings.concat(@engine.scan(wf))
end
unless has_dependabot_actions
findings << Finding.new(
rule: "missing-dependabot",
severity: :low,
file: "dependabot.yml",
line: 0,
code: nil,
message: "No Dependabot configuration for github-actions ecosystem",
fix: "Add package-ecosystem: github-actions to .github/dependabot.yml"
)
end
unless has_zizmor
findings << Finding.new(
rule: "missing-zizmor",
severity: :low,
file: "(missing)",
line: 0,
code: nil,
message: "No zizmor static analysis workflow found",
fix: "Add a security_zizmor.yml workflow for GitHub Actions static analysis"
)
end
end
if @client.respond_to?(:fetch_platform_configs)
platform_configs = @client.fetch_platform_configs
platform_configs.each do |config|
next unless scan_platform?(config[:platform])
platform_scanner = case config[:platform]
when :gitlab
defined?(Platforms::GitLab) ? Platforms::GitLab.new(config[:content], filename: config[:filename]) : nil
when :bitbucket
defined?(Platforms::Bitbucket) ? Platforms::Bitbucket.new(config[:content], filename: config[:filename]) : nil
end
findings.concat(platform_scanner.scan) if platform_scanner
end
end
findings.select! { |f| severity_passes?(f.severity) }
if @policy.loaded?
findings.reject! { |f| @policy.ignored?(f.file) }
findings.reject! { |f| @policy.excepted?(f) }
findings.map! { |f|
override = @policy.rule_severity(f.rule)
if override == :off
nil
elsif override
Finding.new(**f.to_h.merge(severity: override))
else
f
end
}.compact!
findings.select! { |f| severity_passes?(f.severity) }
end
output = @formatter.format(
repo: repo,
workflow_count: workflow_count,
findings: findings
)
{ output: output, findings: findings, workflow_count: workflow_count }
end
|