Arrange Act Assert

Jag Reehals thinking on things, mostly product development

npm install runs code you never read

15 Jun 2026

You run npm install without thinking. It looks like a download step. It is a trust decision.

Every package that resolves into your tree can run code the moment it installs, with the same access you have: your SSH keys, the npm token in ~/.npmrc, your cloud credentials, your .env. Not the package you typed. Any of the hundreds underneath it. You approved none of them by name, and the package manager never asked.

The fix is not to read more or trust less. It is to run that install somewhere your secrets are not.

Read More →

The GitHub and npm settings open source maintainers should turn on before they need them

08 Jun 2026

In the middle of a supply-chain incident, the maintainer is not just fixing packages. They are locked out of their account, answering reports, trying to contact registries, trying to warn users, and trying to prove what happened.

That is the part we do not talk about enough.

Most open source maintainers are not companies. They do not have incident response teams. They do not have a security department. They have a GitHub account, an npm account, a laptop, and a lot of people depending on them.

Security advice often assumes the maintainer is the weak link. That is backwards. The maintainer is the last line of defence, usually unpaid, usually alone, and often locked out of the systems they need during the incident.

This is the checklist I wish every maintainer had before something goes wrong. No single setting saves you, so it works in layers: the account, the branch, the release path, the workflow, the tokens, the files, the tripwires, and the recovery plan.

Read More →

The trusted publishing setting that would have blocked the npm snapshot-branch attacks

08 Jun 2026

In June 2026, a self-propagating npm worm compromised maintainer accounts and republished their packages with malware inside. Maintainers woke to hundreds of malicious versions across dozens of packages, often published in a few minutes overnight.

Many of those versions went out through npm's trusted publishing, the tokenless way to publish from CI, and they carried valid provenance. The green badge, the Sigstore attestation, the "built from this repo by this workflow" proof: all real.

The worm never needed an npm password for those publishes. It used the release pipeline itself.

Trusted publishing remains the right approach. Many configurations leave one field blank, and that blank field is the gap. Closing it takes about five minutes per package. This post shows the attack and the settings that would have stopped the snapshot-branch half of it.

Read More →

Secure AI Apps Start With Functions, Not SQL

13 May 2026

If you're building AI features into your product, the temptation is to hand the model a database connection and let it write SQL.

It feels powerful. It feels like the modern way.

It's the wrong place to start.

The same reasoning applies whether you're building a CLI, a Slack bot, an MCP server, or an agent.

Secure AI Apps Start With Functions, Not SQL

Read More →

node-env-resolver Makes Safe, Typed Node Config the Default

23 Apr 2026

Liran Tal is spot on in his Environment variables and configuration anti-patterns in Node.js applications post

You may inadvertently expose sensitive information like database credentials and API keys as part of error messages, stack traces, and other forms of data returned to consuming clients.

He explains why process.env feels safe right up until it isn't.

You add dotenv.config() on line one, scatter process.env.DB_PASSWORD across twelve files, then someone's error reporter serialises a request object and your Stripe key ends up in a third-party log.

If you've shipped a Node app, you've probably seen some version of this happen.

His anti-pattern example nails it:

const port = process.env.PORT || 3000;
const dbUsername = process.env.DB_USERNAME;
const dbPassword = process.env.DB_PASSWORD;
const dbHost = process.env.DB_HOST;
const apiBaseUrl = process.env.API_BASE_URL;
const apiToken = process.env.API_TOKEN;

Untyped. Unvalidated. Globally readable. One step away from leaking through logs, traces, or error reporters.

But there's still a gap...

Read More →

Log the Fingerprint, Not the Secret

21 Apr 2026

When something goes wrong with your application's configuration, you need to know what was loaded and where it came from.

Most tools for answering that question either tell you too much or nothing at all.

There's a third option most people haven't considered.

Log the Fingerprint, Not the Secret

Read More →

Your .env File Is Not a Secret Store

21 Apr 2026

Most teams make one of two mistakes with secrets.

The first is obvious.

The second is more common in teams that have already fixed the first one.

Both come from the same misunderstanding about what a .env file is supposed to do.

Your .env File Is Not a Secret Store

Read More →