GitHub has published the first consolidated map of every supply chain defense it has shipped across npm and GitHub Actions since late 2025 — nine controls in total, each targeting a specific step in the attack chain that compromised packages carrying 518 million weekly downloads. The blog post, authored by principal engineers Greg Ose and Zachary Steindler and published July 28, 2026, is the clearest picture GitHub has offered of what is defended, what each control disrupts, and where the gaps remain. The gap that stands out: the network egress firewall — the only control in the set that targets credential exfiltration itself — is still in technical preview. It logs outbound traffic from workflow runs but does not yet block it.
For any developer or engineering team running npm packages or GitHub Actions-based CI/CD pipelines, this matters immediately. Every other control in the set limits the pathways through which an attacker can gain code execution or steal credentials. The egress firewall is what would cut off the call-home step after those defenses fail — and right now, that step remains unblocked.
What the Attack Chain Actually Looks Like
GitHub’s post describes the attack pattern with unusual specificity, and understanding it is necessary to evaluate which control does what.
The attacks that battered the npm ecosystem from September 2025 through July 2026 — the Shai-Hulud worm, the Axios compromise, the Miasma wave against Red Hat’s official namespace, the Mastra attack that backdoored 144 AI-focused packages in 88 minutes — did not require any single vulnerability. They chained together multiple weaknesses. A phishing email or a poisoned pull request gives an attacker initial code execution in a CI/CD runner. That runner holds long-lived credentials: npm publish tokens, GitHub personal access tokens, OIDC tokens. The attacker reads those credentials from the runner’s memory. With credentials in hand, they publish malicious versions of the packages the runner is authorized to publish. Those malicious versions propagate into the dependency trees of thousands of downstream projects via automated dependency update tools before anyone notices.
This is why GitHub’s post uses the phrase "holistic approach" and why that phrase is not a platitude in this context. Breaking only one link in this chain does not stop the attack. Breaking most of them slows it enough for detection to work. That is what the nine shipped controls attempt to do — together, they represent a shift from patching individual vulnerabilities to enforcing default-deny architecture at each phase of the attack pattern.
Initial Access: Locking the Front Door
Four of the nine controls target the initial-access phase — the moment an attacker first gains a foothold.
The most straightforward targets account takeover at the maintainer level. High-impact npm accounts now enter a 72-hour read-only mode when a user changes their email address or uses a two-factor authentication recovery code. The delay reflects how phishing campaigns work in practice: an attacker who has stolen a maintainer’s credentials typically needs to change the account’s registered email before the real owner can be alerted and reclaim control. A 72-hour window lets the genuine maintainer notice and recover before the account can be used to push malicious packages.
The remaining three controls in this phase target CI/CD pipeline vulnerabilities — specifically the pull_request_target attack pattern that security researchers at GitHub Security Lab named a "pwn request" in 2021 and that drove some of the most damaging supply chain incidents of the past two years.
The mechanism is worth understanding precisely, because it appears in production workflows at Fortune 500 companies and is still present in millions of repositories. The pull_request_target event was introduced by GitHub in 2020 to solve a legitimate problem: the standard pull_request event runs in the context of a forked repository, with no access to the base repository’s secrets, tokens, or shared cache. That makes it useless for automated tasks — comment posting, label assignment, coverage reports — that require elevated permissions. pull_request_target runs in the base repository’s context, with full access to all of those resources. The danger is that developers began reaching for it in cases where they also wanted to run untrusted code: testing a contributor’s diff, generating an authenticated coverage report against the actual change. When that workflow checks out the fork’s pull request head — code the maintainer has not reviewed — and executes it with base-repository credentials in scope, any attacker who can open a pull request can run arbitrary code with the target repository’s full credential set.
The July 14 AsyncAPI attack demonstrated the vector directly. An attacker opened 37 pull requests against the AsyncAPI generator repository, camouflaging the exploit in noise. Within an hour, a misconfigured pull_request_target workflow had executed the attacker’s code, exposed the project’s npm publish token, and enabled the attacker to push malicious commits under a legitimate automated identity — five backdoored package versions across four packages that together see more than 2.25 million weekly downloads.
GitHub’s response has three parts. The actions/checkout action now refuses by default to fetch fork pull request code inside pull_request_target and workflow_run workflows; workflows can re-enable the blocked behavior by setting allow-unsafe-pr-checkout: true, a flag name deliberately chosen to be conspicuous in code review. A second control lets enterprise, organization, and repository operators set policies on who is allowed to trigger workflows and what trigger types are permitted. A third closes a subtler escalation path: less-trusted workflows can no longer write to the cache shared with more-privileged workflows, which had been a route for turning limited code execution into access to the credentials held by release and publishing pipelines.
What the checkout enforcement does not cover, and what every team should audit now: workflows that use run: blocks invoking git or the GitHub CLI to pull untrusted refs remain fully vulnerable. The fix is scoped to actions/checkout; the underlying event trigger is not.
Credential Exfiltration: Making Secrets Worthless Before They Are Stolen
Two controls target the exfiltration phase — the moment an attacker with code execution reads long-lived credentials from runner memory.
The most structurally significant is trusted publishing, which GitHub has now extended to include CircleCI as a provider. Trusted publishing removes long-lived credentials from CI/CD pipelines entirely. Instead of storing an npm publish token in a repository secret — where any workflow running in that repository’s context can read it — trusted publishing uses short-lived, scoped OIDC tokens that are valid for exactly one publish operation and expire immediately afterward. There is nothing to steal because there is no persistent credential present. The practical action for any team not yet using trusted publishing: migrate off long-lived npm tokens in CI/CD. GitHub now supports trusted publishing from GitHub Actions, CircleCI, and several other providers.
The second exfiltration-phase control is the one that is not yet complete: the network egress firewall. Currently in technical preview, it logs all outbound network traffic from Actions workflow runs. The capability that would close the exfiltration gap — policy enforcement and blocking of unexpected outbound connections — is listed as "future work." The preview is available and worth enabling now: building an egress allowlist in monitoring mode before blocking mode ships means that when enforcement arrives, it can be activated immediately rather than requiring an emergency audit under attacker pressure.
The architectural detail matters. Most existing egress controls for GitHub Actions, including StepSecurity’s harden-runner, run inside the runner virtual machine. An attacker who achieves root access inside the runner can disable them. GitHub’s native firewall is placed at the network infrastructure level outside the runner virtual machine, where root access inside the VM provides no leverage. That is why this control targets the exfiltration phase specifically: it is the layer an attacker cannot bypass through code execution alone, which is why it is also the hardest to build and the last to ship.
Propagation: Breaking the Speed Advantage
Once an attacker has credentials, the attack’s remaining leverage is speed. Every malicious package published needs to reach as many downstream dependency trees as possible before detection and removal. Three of the nine controls target this race.
Staged publishing, now generally available on npm, requires human two-factor authentication approval before a package version staged by automated CI/CD becomes publicly installable. The control decouples the credentials used in automation from the credentials that can make a package publicly available. Even with a stolen CI/CD token, an attacker cannot push a malicious version through to the registry without completing a live 2FA challenge — one that only an interactive human can satisfy. Staged publishing is opt-in; teams that have enabled it and configured it for their publishing workflows have effectively severed the attack chain from credential theft to malware distribution.
npm v12, which shipped July 8, 2026, addresses the second propagation vector: install-time code execution. For the entirety of npm’s 16-year history, any package in a dependency tree — including packages several layers deep that a developer never directly chose — could run arbitrary shell commands at install time via preinstall, install, and postinstall script hooks. Attackers used these hooks to exfiltrate credentials the moment a developer or CI/CD pipeline ran npm install, without waiting for any application code to execute. npm v12 disables these scripts by default. It also blocks dependencies resolved from git repositories and from remote URLs by default — two additional execution paths that had been used as evasion techniques when install-script monitoring appeared.
The practical migration path: upgrade to npm 11.16.0 now to see warning-mode previews of every script and dependency that v12 would block, use npm approve-scripts to build an explicit allowlist of the scripts your project genuinely needs, and commit that allowlist before upgrading. Note the failure mode that most migration guides skip: a blocked native build under npm v12 can still exit with code 0 — a silent green CI run that hides a broken build.
The third propagation control is the one most directly targeted at attacker economics. Dependabot now waits three days after a package release before opening a version-update pull request. The reasoning is simple: attackers publishing a malicious package version rely on automated dependency update tools pulling it into downstream projects before the security community has time to notice and remove it. A three-day window gives monitoring services — Socket, Sonatype, StepSecurity, and CISA’s Known Exploited Vulnerabilities catalog — time to flag malicious releases before they reach any project’s code. Security updates still open immediately, so critical patches are never delayed by this cooldown. The cooldown can be adjusted or disabled per-repository via the cooldown option in .github/dependabot.yml.
Incident Response: Shortening the Recovery Window
The final two controls accept that some attacks will succeed despite the rest and focus on limiting the damage window after a compromise has already occurred.
Self-service credential revocation now lets any enterprise admin or member instantly revoke all credentials for a given user, building on enterprise-wide credential management tools released in February 2026. The expanded credential revocation API, which shipped in March 2026, extends this capability to GitHub OAuth and GitHub App tokens — not only personal access tokens — enabling revocation of leaked credentials wherever they appear and regardless of how they were exfiltrated.
The practical note for incident response: when a supply chain attack is detected, every second between detection and credential revocation is a second the attacker retains publish access. These controls make that window a deliberate decision — one a team can close in a single operation rather than hunting through credential stores manually.
What Remains Unaddressed
GitHub’s post is notable for naming limits as well as capabilities, and three gaps are worth making explicit for any team conducting a security audit.
First: workflows that check out untrusted fork code using run: blocks with git or the GitHub CLI are not protected by the actions/checkout enforcement. The July 20 backport closed the most common pattern; it did not close the category. Any workflow file that combines pull_request_target with an explicit git fetch or gh pr checkout remains a pwn-request target.
Second: the network egress firewall in blocking mode has not yet shipped. Until it does, any attacker who achieves code execution inside a GitHub Actions runner can exfiltrate credentials to an external domain. The logging-mode preview is available and worth enabling — it documents your pipeline’s normal egress behavior, which becomes the basis for an enforcement policy when blocking arrives. Enrollment is available at the GitHub Actions native egress firewall early access repository.
Third: npm v12’s install-script blocking does not close the load-time execution path. A malicious package that moves its payload from a postinstall hook into its main module’s entry point will still execute the moment application code imports it. Registry monitoring, provenance attestation, and explicit dependency review remain necessary layers that no default change eliminates.
The larger framing — the one the original description of these controls as "multi-layer defenses" understates — is that nine shipped controls represent a genuine architectural shift from implicit trust to explicit allowlisting across the npm and GitHub Actions ecosystem. The equivalent shift took years in HTTPS adoption, container image signing, and certificate revocation. It is now underway for software package infrastructure. What GitHub’s post marks is not the completion of that shift but the point at which the shift has enough layers that attackers face meaningful resistance at every phase of the attack chain — except one.
Frequently Asked Questions
Does enabling staged publishing on npm break my existing automated release pipeline?
If your pipeline uses a long-lived npm publish token stored as a CI/CD secret, enabling staged publishing means that token can no longer complete a publish without a human 2FA approval step. You will need to decide whether to migrate to trusted publishing — which removes the long-lived token entirely and uses short-lived OIDC tokens instead — or to configure your release workflow so that the final publish step is gated on a manual approval. Staged publishing is currently opt-in; it does not change anything for packages whose maintainers have not enabled it.
What is the Dependabot cooldown and can I disable it for packages where I need faster updates?
The Dependabot cooldown introduces a mandatory three-day delay before Dependabot opens a version-update pull request for any new package release. It applies to version updates only; security updates still open immediately. If your team needs faster version updates for specific packages — for example, an internal package where you control the release — you can configure a shorter window or disable the cooldown entirely using the cooldown option in your .github/dependabot.yml file. GitHub Enterprise Server teams should note that the new default takes effect in GHES 3.23.
Why is the network egress firewall the last control to ship, and how can I prepare for blocking mode now?
The network firewall operates outside the runner virtual machine at the infrastructure level, which is why it is more complex to build and more significant as a defense: it cannot be disabled by an attacker who gains root access inside the runner, unlike tools that run as processes inside the VM. Monitoring mode is available now through the early access program at github.com/github-early-access/actions-native-egress-firewall. Enrolling your most critical workflows in monitoring mode today means you will be building the egress allowlist that blocking mode will enforce — so that when enforcement ships, you can activate it without an emergency audit. The timeline for blocking-mode GA has not been specified by GitHub.
Do these nine controls protect workflows that are already pinned to a specific commit SHA rather than a floating tag?
Workflows pinned to a specific commit SHA, a minor version, or a patch version did not receive the automatic backport of the actions/checkout safer defaults on July 20, 2026. Those workflows must be updated manually to actions/checkout@v7 or a supported floating major tag (v2 through v6) to inherit the new protection. Dependabot is the recommended upgrade path. Until that upgrade is complete, those workflows remain vulnerable to the pwn-request attack pattern if they use pull_request_target or workflow_run with a fork checkout.
Enjoyed this article? Sign up for our newsletter to receive regular insights and stay connected.

