Skip to content

[static-analysis] RGS-012: Secret Exfiltration via Outbound HTTP Request (4 workflows) #30534

Description

@github-actions

Runner-Guard Security Finding

Rule: RGS-012 — Secret Exfiltration via Outbound HTTP Request
Severity: High
Affected Workflows: 4
Total Findings: 8

Description

Runner-Guard's source-to-sink taint analysis detected run: blocks containing outbound HTTP request commands (curl, wget, etc.) targeting non-GitHub domains in job contexts that have access to secrets or publishing capabilities.

This pattern is a strong indicator of credential exfiltration — the primary objective of most GitHub Actions supply-chain attacks. Attackers who achieve code execution in a CI runner use outbound HTTP to exfiltrate stolen secrets to attacker-controlled infrastructure.

Impact

  • Sensitive secrets, tokens, or deployment credentials may be sent to external domains
  • Any external HTTP request combined with secrets access is a high-confidence risk indicator
  • The combination of untrusted event triggers + outbound HTTP + secrets access creates a full exfiltration path

Affected Workflows

Workflow File Line Context
daily-model-inventory daily-model-inventory.lock.yml (see run logs) Outbound HTTP + secrets access
docs-noob-tester docs-noob-tester.lock.yml 462 Outbound HTTP to non-GitHub domain
unbloat-docs unbloat-docs.lock.yml 549 curl to localhost (dev server readiness check)
visual-regression-checker visual-regression-checker.lock.yml 405, 739 curl to localhost (dev server readiness)

Sample Finding (unbloat-docs.lock.yml:549)

- name: Wait for documentation server readiness
  run: |
    STATUS=""
    for i in $(seq 1 45); do
      STATUS=$(curl -s -o /dev/null -w "%{http_code}" (localhost/redacted)
      [ "$STATUS" = "200" ] && echo "Server ready" && break
      sleep 3
    done

Note: The localhost curl calls are likely false positives (health checks against a local dev server), but they fire in jobs that also have access to secrets — which triggers RGS-012's taint analysis.

Remediation

  1. Review each flagged workflow — distinguish between:
    • localhost HTTP calls (health checks — likely false positives)
    • External domain HTTP calls (higher risk — audit carefully)
  2. For localhost calls: Consider suppressing the finding with a runner-guard annotation, or restructure the job to separate the HTTP check from the secrets-access context
  3. For external domain calls: Verify the domain is trusted and the request does not include secret values in headers, body, or query parameters
  4. Principle of least privilege: Split jobs so that secrets-bearing jobs do not also make arbitrary outbound HTTP calls
  5. Network controls: Consider adding firewall rules to restrict outbound HTTP from runner jobs to known-good domains only

False Positive Assessment

Based on the flagged step names ("Wait for documentation server readiness", "Wait for dev server"), most findings appear to be localhost health check polls — a common CI pattern for waiting on a local dev server. These are likely false positives for actual exfiltration, but the pattern is correct to flag because:

  • The same job also has write permissions / secrets access
  • A compromised action could swap localhost for an external endpoint

Recommendation: Confirm these are localhost calls, then add appropriate suppressions.


Detected by runner-guard v2.6.0 — CI/CD source-to-sink vulnerability scanner
Workflow run: https://github.com/github/gh-aw/actions/runs/25418588621

Generated by Static Analysis Report · ● 451.6K · ◷

  • expires on May 13, 2026, 5:53 AM UTC

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions