Infra Audit6 min readUpdated November 4, 2026

Four Ways Your CI Secrets Leave the Building

Printed in logs, handed to fork PRs, passed to third-party actions, or carried by an over-privileged token. Each path has a one-line fix.

Lock down four paths: mask or remove secret-printing steps, never check out PR head in pull_request_target, pin third-party actions to SHAs, and set minimal token permissions per workflow.

GitHub masks exact secret values in logs, but any transformation defeats it: base64, substring, concatenation. A debug step that prints an encoded credential leaks it to anyone who can read the run log, including fork PR authors on public repos. The audit greps workflow steps for secret references inside echo, export and debug contexts.

Path one: the log

GitHub masks exact secret values in logs, but any transformation defeats it: base64, substring, concatenation. A debug step that prints an encoded credential leaks it to anyone who can read the run log, including fork PR authors on public repos. The audit greps workflow steps for secret references inside echo, export and debug contexts.
GitHub masks exact secret values in logs, but any transformation defeats it: base64, substring, concatenation. A debug step that prints an encoded credential leaks it to anyone who can read the run log, including fork PR authors on public repos. The audit greps workflow steps for secret references inside echo, export and debug contexts.

Path two and three: forks and third parties

pull_request_target with a PR-head checkout runs attacker code with your secrets. A third-party action pinned to a mutable tag can be repointed to an exfiltrator. Fixes: plain pull_request for code checks, full SHA pins everywhere. Our repo's CI enforces both, and zizmor blocks new violations at PR time.
pull_request_target with a PR-head checkout runs attacker code with your secrets. A third-party action pinned to a mutable tag can be repointed to an exfiltrator. Fixes: plain pull_request for code checks, full SHA pins everywhere. Our repo's CI enforces both, and zizmor blocks new violations at PR time.

Path four: the token

The default GITHUB_TOKEN can carry write permissions a compromised step can abuse: push code, edit releases, comment as the repo. The fix is permissions: contents: read at the top, raised per job only where a step genuinely writes. The audit reads every workflow's permissions block and flags the missing ones.
The default GITHUB_TOKEN can carry write permissions a compromised step can abuse: push code, edit releases, comment as the repo. The fix is permissions: contents: read at the top, raised per job only where a step genuinely writes. The audit reads every workflow's permissions block and flags the missing ones.

Get the skill

The checks in this guide come from the roqy audit skill, open source at https://github.com/roncoo-2/roqy-audit. It runs read-only against your own account, produces findings with verdicts (confirmed, needs_validation, rejected), and was validated on a live canary AWS account where 9 planted misconfigurations were detected 9 out of 9 times.
The checks in this guide come from the roqy audit skill, open source at https://github.com/roncoo-2/roqy-audit. It runs read-only against your own account, produces findings with verdicts (confirmed, needs_validation, rejected), and was validated on a live canary AWS account where 9 planted misconfigurations were detected 9 out of 9 times. The full canary report is in the repository under docs/runs. Copy the skill into any coding agent, point it at your stack, and get the same report for your account.

4 Tips to Get Started

1

Set permissions: contents: read at workflow level, raise per job only where needed.

2

Pin every action to a full commit SHA. A mutable tag is a supply-chain door.

3

echo $SECRET in a step prints to the log. GitHub masks known secrets, but transformed values leak.

4

Run zizmor on the repo: it finds the leak paths automatically.

Ready to Stop Worrying About Infra?

Knowledge is the first step. Get a free 1-hour diagnostic and see where your infrastructure leaks time, money, and focus.

R

Ron Cohen — DevOps engineer & founder, roqy.io

Content reviewed by the roqy.io team. Our guides are based on publicly available data.

Disclaimer: This content is for informational and educational purposes only. It does not constitute professional advice or a guarantee of specific results. Infrastructure needs vary by team, stack, and stage. Consult a qualified engineer for advice tailored to your situation.

Frequently Asked Questions

How do GitHub Actions secrets leak?

Four main paths: a step prints the secret or a transformed value into the run log; a pull_request_target workflow checks out attacker-controlled PR code that exfiltrates secrets; a third-party action receives the secret and forwards it; or the GITHUB_TOKEN has write permissions an injected step can abuse. Each path has a one-line fix.

Why pin GitHub Actions to a commit SHA?

A mutable tag like v4 can be repointed to malicious code by the maintainer or by an account compromise. Pinning to a full commit SHA freezes the code you reviewed. OWASP lists tag pinning as a supply-chain risk; SHA pinning is the fix.

How do I scan my workflows for secret leaks?

Run zizmor on the repository: it detects template injection, excessive permissions, pull_request_target misuse and unpinned actions. Add gitleaks for secrets committed in code. Our own repo runs both on every pull request.

Get the DevOps Ecosystem Behind You

One accountable engineer. Full platform behind him. Month-to-month, no lock-in.