Class: Rules::DangerousLifecycleScripts

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

Constant Summary collapse

INSTALL_CMDS =
[
    { match: /\bnpm\s+(install|ci)\b/, safe: /--ignore-scripts/, name: "npm" },
    { match: /\bpnpm\s+install\b/, safe: /--ignore-scripts/, name: "pnpm" },
    { match: /\byarn\s+install\b/, safe: /--ignore-scripts/, name: "yarn" },
    { match: /\bbun\s+install\b/, safe: /--ignore-scripts|--no-scripts/, name: "bun" },
]

Instance Method Summary collapse

Instance Method Details

#check(workflow) ⇒ Object



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

def check(workflow)
    return [] unless workflow_has_secrets?(workflow)

    findings = []

    workflow.raw_lines.each_with_index do |line, i|
        next if line.strip.start_with?("#")

        INSTALL_CMDS.each do |cmd|
            next unless line.match?(cmd[:match])
            next if line.match?(cmd[:safe])

            findings << finding(workflow,
                line: i + 1,
                code: line.strip,
                message: "#{cmd[:name]} install runs lifecycle scripts in a workflow with secrets — a compromised dependency can exfiltrate credentials",
                fix: "Add --ignore-scripts, then explicitly rebuild trusted native deps: #{cmd[:name]} rebuild sharp esbuild"
            )
        end
    end

    findings
end

#descriptionObject



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

def description = "Package install without --ignore-scripts in workflow with secrets"

#nameObject



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

def name = "dangerous-lifecycle-scripts"

#severityObject



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

def severity = :medium