Class: Rules::MissingEnvProtection

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

Constant Summary collapse

PUBLISH_INDICATORS =
Regexp.union(
    # JavaScript / TypeScript
    /\bnpm\s+publish\b/,
    /\bpnpm\s+publish\b/,
    /\byarn\s+publish\b/,
    /\bnpx\s+pkg-pr-new\b/,
    # Python
    /\btwine\s+upload\b/,
    /\bpoetry\s+publish\b/,
    /\bflit\s+publish\b/,
    /\buv\s+publish\b/,
    # Ruby
    /\bgem\s+push\b/,
    /\brake\s+release\b/,
    # Rust
    /\bcargo\s+publish\b/,
    # Java / Kotlin
    /\bmvn\s+deploy\b/,
    /\bgradle\s+publish\b/,
    /\.\/gradlew\s+publish\b/,
    # .NET
    /\bdotnet\s+nuget\s+push\b/,
    /\bnuget\s+push\b/,
    # Docker
    /\bdocker\s+push\b/,
    /\bdocker\s+buildx\s+build\b.*--push/,
    # Infrastructure
    /\brailway\s+up\b/,
    /\bcdk\s+deploy\b/,
    /\bterraform\s+apply\b/,
    /\bpulumi\s+up\b/,
    /\bfly\s+deploy\b/,
    /\bheroku\s+container:push\b/,
    # Homebrew
    /\bbrew\s+bump-formula-pr\b/,
)

Instance Method Summary collapse

Instance Method Details

#check(workflow) ⇒ Object



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
# File 'lib/rules/missing_env_protection.rb', line 44

def check(workflow)
    findings = []

    workflow.jobs.each do |job_id, job|
        next if job.key?("environment")

        steps = workflow.steps(job)
        has_publish = steps.any? { |s| s["run"]&.match?(PUBLISH_INDICATORS) }

        has_oidc = oidc_id_token?(workflow.permissions(scope: :job, job: job)) ||
                             oidc_id_token?(workflow.permissions(scope: :workflow))

        if has_publish || has_oidc
            line = workflow.line_of(/^\s+#{Regexp.escape(job_id)}:/)
            findings << finding(workflow,
                line: line || 0,
                code: "#{job_id}:",
                message: "Publish/deploy job without environment protection — no human gate before publication",
                fix: "Add environment: <name> with required reviewers"
            )
        end
    end

    findings
end

#descriptionObject



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

def description = "Publish/deploy job without GitHub Environment protection"

#nameObject



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

def name = "missing-env-protection"

#severityObject



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

def severity = :medium