Class: Rules::GithubScriptInjection

Inherits:
Base
  • Object
show all
Includes:
GuardPatterns
Defined in:
lib/rules/github_script_injection.rb

Constant Summary collapse

PATTERN =
/\$\{\{\s*(#{DANGEROUS_CONTEXTS.map { |c| Regexp.escape(c) }.join('|')})/

Constants included from GuardPatterns

Rules::GuardPatterns::DANGEROUS_CONTEXTS, Rules::GuardPatterns::JOB_PROPERTIES, Rules::GuardPatterns::SAFE_TRIGGERS

Instance Method Summary collapse

Methods included from GuardPatterns

#guarded_by_safe_event?, #safe_trigger_only?, #strip_inline_comment

Instance Method Details

#check(workflow) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/rules/github_script_injection.rb', line 13

def check(workflow)
    findings = []

    return [] if safe_trigger_only?(workflow)

    workflow.raw_lines.each_with_index do |line, idx|
        line_num = idx + 1
        next if line.strip.start_with?('#')
        next unless line.match?(PATTERN)
        next unless in_github_script_block?(workflow, line_num)
        next if guarded_by_safe_event?(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 actions/github-script — JavaScript injection risk",
            fix: "Use context.payload instead: context.payload.pull_request.title"
        )
    end

    findings
end

#descriptionObject



8
# File 'lib/rules/github_script_injection.rb', line 8

def description = "Attacker-controllable ${{ }} expression in actions/github-script"

#nameObject



7
# File 'lib/rules/github_script_injection.rb', line 7

def name = "github-script-injection"

#severityObject



9
# File 'lib/rules/github_script_injection.rb', line 9

def severity = :critical