Class: Rules::ShellInjectionExpr

Inherits:
Base
  • Object
show all
Defined in:
lib/rules/shell_injection_expr.rb

Constant Summary collapse

DANGEROUS_CONTEXTS =
%w[
  github.event.pull_request.title
  github.event.pull_request.body
  github.event.pull_request.head.ref
  github.event.pull_request.head.label
  github.event.issue.title
  github.event.issue.body
  github.event.comment.body
  github.event.review.body
  github.event.discussion.title
  github.event.discussion.body
  github.event.workflow_run.head_branch
  github.head_ref
  github.actor
  github.triggering_actor
].freeze
PATTERN =
/\$\{\{\s*(#{DANGEROUS_CONTEXTS.map { |c| Regexp.escape(c) }.join('|')})/

Instance Method Summary collapse

Instance Method Details

#check(workflow) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/rules/shell_injection_expr.rb', line 26

def check(workflow)
  findings = []
  workflow.lines_of(PATTERN).each do |line_num|
    line = workflow.line_content(line_num)
    next unless in_run_block?(workflow, line_num)

    match = line.match(PATTERN)
    next unless match

    findings << finding(workflow,
      line: line_num,
      code: line.strip,
      message: "Attacker-controllable expression ${{ #{match[1]} }} in run: block — shell injection risk",
      fix: "Move to env: block and reference as $ENV_VAR in the shell"
    )
  end
  findings
end

#descriptionObject



4
# File 'lib/rules/shell_injection_expr.rb', line 4

def description = "Attacker-controllable ${{ }} expression in run: block"

#nameObject



3
# File 'lib/rules/shell_injection_expr.rb', line 3

def name = "shell-injection-expr"

#severityObject



5
# File 'lib/rules/shell_injection_expr.rb', line 5

def severity = :critical