Skip to main content
Blog
Cloud SecurityDevOps

Secure Defaults Are a Safeguard, Not a Nice-to-Have

Recent npm supply-chain attacks and the CISA GovCloud leak point to one lesson: secure defaults are an essential safeguard — and backward compatibility is no excuse to weaken them.

ZapWerx Team 9 min read
Secure Defaults Are a Safeguard, Not a Nice-to-Have

A default is a decision the maintainers of a tool make on behalf of everyone who never changes it. And most people never change it. For the majority of installations, the default is not a starting point — it is the final configuration. That makes the choice of defaults one of the most consequential security decisions in any piece of software, and it is made by someone other than you.

The U.S. Cybersecurity and Infrastructure Security Agency puts it plainly in its Secure by Design guidance: a product is “secure by default” when it ships with secure configurations already enabled, protecting users — in CISA’s words — “without requiring a customer to be a security expert.”

The past eight months have delivered an unusually clear set of case studies. Several show secure defaults doing exactly their job. One shows, in painful detail, what happens when someone deliberately switches a secure default off.

#The npm ecosystem’s hard year

Few parts of the software supply chain have been tested as relentlessly as the npm registry.

In September 2025, a phishing campaign against a prominent maintainer compromised eighteen packages — including chalk and debug. Together, the affected packages see billions of weekly downloads. Days later, the self-propagating Shai-Hulud worm tore through more than 500 packages, harvesting GitHub tokens and cloud credentials from every machine that installed an infected version and using them to infect still more packages. In March 2026, two malicious releases of axios — one of the most depended-on packages in the ecosystem — shipped a payload that reached out to attacker infrastructure.

Then, on 11 May 2026, the group tracked as TeamPCP published 84 malicious versions across 42 @tanstack/* packages in a six-minute window. TanStack’s own postmortem is worth reading in full, because the attack chain is a guided tour of weak defaults.

These incidents are not isolated bad luck. They are the predictable result of a supply chain whose defaults assume trust. Both NIST’s Secure Software Development Framework and the CNCF’s Software Supply Chain Security Best Practices treat third-party code as untrusted until proven otherwise — the opposite of how most package tooling has historically behaved.

#Choosing tools is choosing defaults

Here is the part teams control directly.

#Package managers

Almost every npm supply-chain payload relies on the same mechanism: install-time lifecycle scripts. When a package declares a preinstall or postinstall script, the classic behavior of npm install is to run it — automatically, with your user’s privileges, before you have run, reviewed, or even imported a single line of the code. Installing a package was enough to be compromised.

This behavior persisted for years in the name of backward compatibility. Plenty of legitimate packages use install scripts to compile native add-ons, so changing the default would “break” them.

pnpm made the other choice. Since late 2025, pnpm ships with strictDepBuilds enabled by default: dependency lifecycle scripts are blocked unless you explicitly allow them. A package that wants to run code at install time now has to be named, by you, on a list. The convenient case still works — it just requires one deliberate line in your configuration instead of silent, universal trust.

This is exactly why the package manager you choose is a security decision, not a matter of taste. This site is built with pnpm for precisely that reason. npm itself has since moved in the same direction, completing a major authentication overhaul in December 2025, and Dependabot can now refuse pull requests for packages younger than an age you set — giving malicious releases time to be caught before they reach you.

#CI triggers

The TanStack attack did not stop at npm. Its entry point was a GitHub Actions trigger — and the contrast between two triggers is the clearest “defaults matter” lesson in this whole story.

When a workflow runs on pull_request, a pull request from a forked repository gets a read-only token and no access to your secrets. That is the secure default, and it is secure for a reason: the code in a fork’s pull request is, by definition, written by someone you have not vetted.

pull_request_target is the escape hatch. It exists, in GitHub’s own words, so that workflows can “label PRs” or “comment on the PR” — tasks that need write access to your repository. It runs with your full secrets and a read-write token. It is safe only as long as it never checks out and runs the pull request’s code. The moment a workflow combines pull_request_target with a checkout of the pull request’s branch, it hands your credentials to a stranger. GitHub Security Lab calls this a “pwn request”; OWASP catalogues it as CICD-SEC-4, Poisoned Pipeline Execution.

That is exactly what happened to TanStack. An attacker forked a repository, opened a pull request, and triggered a pull_request_target workflow that checked out and executed the fork’s code. From there they poisoned the Actions build cache, and when a maintainer’s legitimate change was later merged, the poisoned cache was restored and used to steal a deployment token out of the runner’s memory.

Notice the shape of the failure. pull_request — the safe default — would not have allowed it. pull_request_target exists only to keep a category of convenience workflow working. The danger was never the default; it was the backward-compatibility hatch built beside it. (GitHub has since hardened that hatch: as of 8 December 2025, pull_request_target workflows run the workflow definition from your default branch rather than the pull request’s base branch.)

#The CISA leak: the default worked; someone turned it off

If npm and pnpm show defaults being debated, the CISA incident shows one being deliberately overridden — by the agency that wrote the doctrine.

In May 2026, security researchers found a public GitHub repository named “Private-CISA.” It had been open for roughly six months. Inside, as Brian Krebs reported, was a file called importantAWStokens containing administrator credentials for three AWS GovCloud accounts, alongside a spreadsheet of plaintext passwords for internal CISA systems. The exposed AWS keys reportedly stayed valid for 48 hours after the repository was taken down.

Here is the detail that matters for this post. GitHub has a feature called push protection that scans commits for credentials and blocks the push when it finds them. It is on by default. It is, in CISA’s own vocabulary, a secure default — a safeguard that protects users without requiring them to be security experts.

The commit history showed that the account owner had turned push protection off.

The safeguard was present. It worked. It would have caught importantAWStokens at the very first git push and refused it. The breach did not happen because a secure default was missing or inadequate. It happened because someone with the access to disable it did so, and then committed the secrets the feature existed specifically to stop. The tooling did its job. A person overrode it. That distinction is the entire argument: when the default is sound, the failure is the override — and the responsibility sits with whoever performed it.

#Backward compatibility is not a security exemption

A theme runs through all of this. Insecure behavior survives because changing it would break something.

npm install ran arbitrary scripts because some packages depend on it. pull_request_target exposes secrets to fork code because some workflows need write access. Both are real compatibility concerns. Neither is a reason to make the dangerous behavior the default.

The fix is not to remove the capability. It is to invert the burden. Make the safe behavior automatic and the dangerous behavior something you opt into — by name, on the record, where a reviewer can see it. pnpm did not delete install scripts; it made you list the ones you trust. GitHub did not delete pull_request_target; it made the safe checkout the default and the dangerous one explicit. AWS did not remove the ability to make an S3 bucket public; since April 2023 it simply stopped doing so by default, so that exposing a bucket is now a deliberate, visible act rather than an accident waiting to happen. The same instinct produced IMDSv2-by-default on EC2 and runs through the Security pillar of the AWS Well-Architected Framework.

Backward compatibility deserves a migration path, a deprecation window, and clear documentation. It does not deserve to be the default. A default that favors “nothing breaks” over “nothing leaks” has simply chosen whose problem the risk becomes — and it chose you.

#What this means for your team

You do not control how npm or GitHub ship their products. You do control the defaults you accept and the ones you override. A short, concrete checklist:

  • Prefer secure-by-default tooling. When two tools do the same job, the one that is safe out of the box is the better choice — measurably, not philosophically.
  • Treat disabling a guardrail as a reviewable security decision. A commit that turns off push protection, allows an install script, or adds pull_request_target should get the same scrutiny as a change to a firewall rule.
  • Audit the defaults you have already changed. Search your workflows for pull_request_target, and especially for any that check out a pull request’s code. Check whether anyone has relaxed push protection or secret scanning across your organization.
  • Make the safe path the easy path. If developers route around a control, the control is badly designed — fix the ergonomics rather than the exception.

Secure defaults are not a finishing touch applied once the real work is done. They are the safeguard that holds when attention lapses, when a deadline looms, when the person at the keyboard is not a security expert and should not have to be. Treat them as essential — because the moment one is switched off, as a federal cybersecurity agency has just demonstrated, that is precisely what they turn out to have been.

#Sources

Tags: supply-chainsecuritynpmci-cdtooling
Share