Class: Rules::GithubScriptInjection

Inherits:
Base
  • Object
show all
Defined in:
lib/rules/github_script_injection.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
44
45
46
# File 'lib/rules/github_script_injection.rb', line 26

def check(workflow)
    findings = []

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

    findings
end

#descriptionObject



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

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

#nameObject



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

def name = "github-script-injection"

#severityObject



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

def severity = :critical