All posts

Malware that strikes at install time, and what GitHub's firewall checks

Security · 4 min read ·

Most of us think of a malicious dependency as code that does damage when the application runs it. GitHub's point in its 20 October 2026 announcement is that a growing number of attacks do not wait that long: they act while the package is being installed, and harvest credentials from the CI runner or the developer's laptop without the package's code ever being executed by your app. By the time a test runs, the token is already gone. GitHub's answer is a package firewall, now in public preview, and it is worth knowing both what it does and how narrow its scope is today.

Actions runner coding agent package firewall cooldown period advisory database attestation downgrade npm registry metadata requests and downloads both pass through
The firewall only helps the machines you point at it. A runner still talking straight to the registry is outside it.

What the firewall inspects

As GitHub describes it, the firewall sits between your endpoints, meaning Actions runners and coding agents, and the upstream registry, and it looks at both metadata requests and package downloads. Today the policies are a configurable cooldown period, a check against the GitHub Advisory Database for malware and vulnerability alerts, and supply-chain checks such as an attestation downgrade. Endpoints have to be configured to use the firewall instead of the registry directly, and if a package is blocked by mistake you can request an exception.

What it does not cover

Be precise about the scope before you plan around it. GitHub says the preview is for GitHub Enterprise Cloud customers, including data residency, and that it currently supports npm packages only. So on a Free or Team plan you do not have it, and for a PHP project nothing in your Composer install goes through it. It is free during the preview, and GitHub says it will later be metered in a way similar to Actions billing.

The publishing side hardened the same month

Two npm changes from 2 October push from the other end. npm stage publish can now create a brand new package: the first version goes into a staged queue, and a maintainer has to promote it before anyone can install it. And unvalidated trusted-publishing configurations now expire 48 hours after they are created, which limits the risk of trusting a repository or project name that later changes owner. A configuration is validated by its first successful publish. npm also now rejects trusted-publishing tokens from issue_comment workflow events, alongside the existing pull_request_target restriction; npm points you to push, release or workflow_dispatch instead.

install only what the lockfile says wait a few days on brand new versions run an advisory audit in CI no long-lived secrets where installs run deeper the last layer limits what a bad install can steal
General practice, not part of GitHub's product. Each layer catches something the one above it misses.

What you can do on any plan

This part is general guidance, not a claim about the firewall. Commit your lockfiles and install from them: npm ci for JavaScript, composer install against composer.lock for PHP. Run an advisory check in CI. --ignore-scripts skips npm lifecycle scripts, but it is not a full defence, because install-time attacks are not only scripts and some packages legitimately need them. A manual cooldown means not upgrading to a version published in the last few days, since most malicious versions are found quickly. And the layer that matters most: do not run installs on a machine that holds long-lived credentials.

npm ci
composer install --no-interaction
composer audit
Assume an install can read every secret on the machine it runs on, and decide what lives on that machine with that in mind.

This site is Laravel with a little JavaScript tooling, so the firewall would only ever cover the smaller half of it. For the PHP side the equivalent is plain: install from the committed composer.lock, run composer audit in CI, and do not let updates land without someone reading them. If you are on Enterprise Cloud, point one runner at the firewall, watch what it blocks for a week, then widen it. Source: GitHub Changelog, package firewall in public preview.

Notes from readers

  1. No notes yet. The first one is the bravest.
Building something like this? I can help. Message me on WhatsApp