Most platform security changes are opt-in, buried in a settings page you'll never visit. The two GitHub shipped on July 28 are not: they're on by default, they act on your code automatically, and the second one can hold your own release if you're not ready for it. If you publish an npm package or run anything in GitHub Actions, your ship checklist changed this week whether you noticed or not.

Here's the whole story in one line: GitHub added a gate at your CI's entrance and a gate at npm's exit, and both can stop traffic — including yours.

Gate one: Actions holds suspicious runs for a human#

The first change targets a specific, ugly attack. Someone gets a foothold — a leaked token, a compromised collaborator — and pushes a malicious workflow whose whole job is to exfiltrate your CI/CD credentials and pivot from there. It's a live pattern, not a hypothetical, and it's exactly how the Mastra-style npm compromises started.

Now, when Actions flags a workflow run as potentially malicious, the run is held: it will not execute until a collaborator with write access reviews and approves it through an authenticated web session. Two details matter for a small team. It's currently scoped to public repositories on github.com. And the approval has to come from an authenticated human with write access — which means an unattended bot cannot approve its own held run. That's the point: the gate exists precisely for the moment your automation has been turned against you.

A normal pipeline sails through untouched. But if you run agents that open or trigger workflows on your behalf, understand the new failure mode — a held run just stops, and it waits for a person, not a retry.

Gate two: npm scans every package before it's installable#

The second change moves the check to the registry's front door. Every newly published npm package is now scanned before it becomes available to install. Based on the result, the package is released normally, held for manual review, or blocked outright. The practical cost: roughly five minutes between npm publish and the version actually being installable.

Budget for that delay. If your release script publishes and then immediately kicks off a deploy that installs the fresh version, you now have a race you didn't have last week. Add the wait, or gate the deploy on the version actually resolving.

The registry stopped trusting "it published" as proof of "it's safe." Your release automation should stop trusting it too.

The fine print that will trip up security builders#

Here's the clause most roundups skipped. Some legitimate packages do things that look malicious to an automated scanner — security tooling, red-team utilities, anything that touches process memory, network internals, or credentials by design. npm now asks maintainers of that dual-use software to declare it up front: a contentPolicy field in package.json, plus a text-only DISCLOSURE file describing the capability and its intended use.

If you ship that kind of tool and don't declare it, you're the false positive — held for manual review while the scanner and a human sort you out. Do the declaration before you publish and you hand the scanner the context it needs to let you through. This is the same tension we flagged when agent skills started shipping as installable packages: powerful-by-design and malicious-by-design can look identical from the outside, so the burden shifts to declaring intent.

Read it alongside the other half of the tightening#

None of this is isolated. Three weeks earlier, npm v12 disabled lifecycle install scripts by default — a postinstall no longer runs automatically on your users' machines. Put the two together and the direction is unmistakable: the registry is closing the doors where arbitrary code used to run for free. Publish-time scanning guards the front door; install-scripts-off guards the users' machines; the Actions hold guards your CI. Same campaign, three gates.

Your updated ship checklist#

Concrete, boring, do it once:

The gates are a genuine gift — free, automatic defense against a class of attack that's been hitting real projects. But defense-by-default is still a change to your pipeline, and the teams that get surprised will be the ones who find out about the five-minute hold from a failed deploy instead of from here. Now you know.