Skip to content

[static-analysis] RGS-012: Secret Exfiltration via Outbound HTTP in docs-noob-tester and visual-regression-checker #29178

Description

@github-actions

RGS-012: Secret Exfiltration via Outbound HTTP Request

Severity: High
Rule: RGS-012 — Tainted data flows from event payload through an HTTP client to an external endpoint, with potential to exfiltrate secrets or environment variables
Detected: 2026-04-29 | Run 25130700074
Findings: 3 total across 2 workflows


Affected Workflows

1. docs-noob-tester.lock.yml — 2 findings

Taint flow pattern:

  • Source: Untrusted event payload (e.g., github.event.pull_request.head.sha, github.event.comment.body, or similar)
  • Sink: HTTP client (curl, wget, fetch, or Actions HTTP client) making an outbound request
  • Risk: If tainted data includes secrets or is used to construct URLs/headers with credentials, those values could be exfiltrated to an attacker-controlled endpoint

Recommended fix:

# Before (vulnerable pattern):
- run: |
    curl -X POST "${{ github.event.inputs.webhook_url }}" \
      -H "Authorization: Bearer ${{ secrets.TOKEN }}"

# After (safe pattern):
- run: |
    # Validate URL is in allowlist before making request
    if [[ "$WEBHOOK_URL" != (internal.example.com/redacted) ]]; then
      echo "Error: URL not in allowlist"
      exit 1
    fi
    curl -X POST "$WEBHOOK_URL" \
      -H "Authorization: Bearer $TOKEN"
  env:
    WEBHOOK_URL: ${{ github.event.inputs.webhook_url }}
    TOKEN: ${{ secrets.TOKEN }}

2. visual-regression-checker.lock.yml — 1 finding

Same taint-flow pattern: event payload data flows into an outbound HTTP call without sanitization or allowlist validation.


Attack Scenario

  1. Attacker submits a pull request or triggers a workflow event with a crafted payload
  2. Workflow reads attacker-controlled data (PR title, branch name, comment body, etc.)
  3. That data is used in constructing or executing an HTTP request
  4. If secrets are included in the request (headers, body, URL params), they are exfiltrated to an attacker-controlled endpoint

Remediation Checklist

  • Identify the specific source-to-sink path in docs-noob-tester.lock.yml (2 instances)
  • Identify the specific source-to-sink path in visual-regression-checker.lock.yml (1 instance)
  • Validate all outbound HTTP destinations against an explicit allowlist
  • Never pass secrets as URL parameters or include them in URLs constructed from untrusted input
  • Use environment variables instead of ${{ secrets.X }} interpolation in run: blocks where possible
  • Audit what data is included in outbound HTTP request bodies/headers

References

Generated by Static Analysis Report · ● 452.4K ·

  • expires on May 6, 2026, 8:08 PM UTC

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