How a GitHub Actions Workflow Can Reach Every Secret in Your Pipeline
A CI workflow is a privileged insider: it can read your named secrets, any credential on disk, and every secret ever committed to your git history.
When attackers hijacked two maintainer accounts in the October 2026 GhostAction campaign, the malicious code they added was tiny: a single workflow file. It did not exploitExploit🛡️Code or technique that takes advantage of a vulnerability to cause unintended behavior, such as gaining unauthorized access. a vulnerabilityVulnerability🛡️A weakness in software, hardware, or processes that can be exploited by attackers to gain unauthorized access or cause harm.. It simply used the access that every GitHub ActionsGitHub Actions🛡️GitHub's built-in automation and CI/CD platform. It runs workflows defined in YAML files under a repository's .github/workflows directory, and those jobs can read the repository's stored secrets and reach the network. workflow already has. To defend a build pipeline you first have to understand what a workflow can actually see, because that trust is the real attack surfaceAttack Surface🛡️The sum of all points where an unauthorized user could attempt to enter or extract data from a system: exposed services, interfaces, accounts, and integrations. Reducing attack surface means removing reachability, not just patching..
The Runner Is a Trusted Insider
A continuous-integration workflow is not an outsider poking at your repository from the network. It is code you invited in, running on a machine that has already authenticated as your project. When GitHub Actions starts a job, it checks out your source, injects an automatically generated token scoped to the repository, and makes available any secrets the workflow references. From inside that job, reading a secret is not an exploit. It is the intended behaviour.
That is why the GhostAction workflow needed no clever trick. It declared the project's own secret names as environment variables, and the platform dutifully filled them in. The same mechanism that lets a legitimate release job publish to a package registry lets a malicious job read the publishing token and mail it to a stranger.
What a Workflow Can Reach
Three categories of credential sit within reach of any job that runs in your repository.
The first is named secrets: the values you store in repository or organisation settings and reference explicitly, such as a registry password or a cloud deployment key. A workflow can only read a named secret if it asks for it by name, which is why the attackers performed reconnaissance first, reading each project's real pipelines to learn which secret names to request.
The second is the checked-out working tree. If a developer ever hardcoded a key in a config file, a `.env` example, or a test fixture, the workflow sees it as plain text on disk and can scan for it with a few lines of pattern matching.
The third, and the one teams forget, is the full commit history. By default a checkout is shallow, fetching only the latest commit. But a workflow can request the complete history, and then every credential ever committed, including ones deleted years ago, is sitting in the diffs waiting to be read. The GhostAction workflow did exactly this, which is why cleaning your current files is not enough and you need a process for how to find and remove secrets hidden in your git history.
How Exfiltration Works
Once a workflow has gathered credentials, sending them out is trivial. A runner has normal outbound network access, so a single command can POST the collected data to any address on the internet. The October campaign used a bare IP over plain HTTP precisely because it is boring and reliable: there is no domain to blocklist and no certificate to inspect.
The data left in clearly tagged batches so the operators could sort it: one stream for named secrets, another for history-mining results. They even captured the lines surrounding each AWS access-key match so an access-key ID and its secret could be reassembled into a working pair. This is not sophisticated engineering. It is a reminder that a workflow with read access to secrets and write access to the network can do everything an attacker wants in a dozen lines of YAML.
Why the Git History Changes the Math
Most incident playbooks assume that rotating the exposed secret ends the exposure. History mining breaks that assumption. A credential that was committed in 2023, noticed, deleted, and replaced is still present in the repository's history, and a rotated replacement does nothing for the original if that original was never truly revoked at the source.
So the question after a GhostAction-style compromise is not "what is in my code now" but "what has ever been in my code." That is a much larger set, and answering it is work you do not want to improvise during an incident.
What This Means for You
The lesson is not that GitHub Actions is unsafe; it is that a workflow is a privileged identity and should be treated like one. Assume any workflow that runs in your repository can read every secret it references, every credential on disk, and, if it asks, every credential in your history. Design around that assumption.
Concretely, that means minimising what secrets exist to be stolen, scoping tokens tightly, and reviewing changes to workflow files with the same care you would give to changes in authentication code. It also means recognising that the most durable protection is to stop storing long-lived secrets at all, which is why short-lived credentials beat rotating secrets after a CI breach. A workflow that has nothing standing to read is a workflow with nothing to leak.
The attackers in October did not break into a vault. They walked in wearing a badge your pipeline handed them. The fix is to stop handing out badges that open everything.