/supply-chain-hardening
Configure install-time cooldowns for npm/bun (minimum release age) and run a sandboxed pre-install scan when the cooldown has to be bypassed. Use when the user asks about supply-chain attacks, npm/bun security, "minimum release age", a "cooldown" for installs, hardening against
$ npx -y skills add jamditis/claude-skills-journalism --skill supply-chain-hardening --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/supply-chain-hardening
Context preview
The summary Claude sees to decide when to auto-load this skill.
Configure install-time cooldowns for npm/bun (minimum release age) and run a sandboxed pre-install scan when the cooldown has to be bypassed. Use when the user asks about supply-chain attacks, npm/bun security, "minimum release age", a "cooldown" for installs, hardening against
SKILL.md
supply-chain-hardening.SKILL.mdname: supply-chain-hardening
description: Configure install-time cooldowns for npm/bun (minimum release age) and run a sandboxed pre-install scan when the cooldown has to be bypassed. Use when the user asks about supply-chain attacks, npm/bun security, "minimum release age", a "cooldown" for installs, hardening against Shai-Hulud-class worms, or how to safely install a package that was just published. Also use after any recent supply-chain incident in the npm ecosystem.
Supply-chain hardening
Defends a journalism toolchain against the dominant npm/bun supply-chain attack pattern: a maintainer account or CI pipeline is compromised, a malicious version ships, and machines install it before anyone notices. Recent example: the **Mini Shai-Hulud TanStack attack (2026-05-11)** compromised 84 versions across 42 `@tanstack/*` packages and exfiltrated AWS / GCP / Vault / GitHub / SSH credentials via a postinstall script.
The defense is **layered** and intentionally simple:
1. **Install-time cooldown** — only install package versions older than N days (default 7). This is the primary defense. By the time the cooldown expires, the security community has almost always flagged a compromised version and the registry has yanked it. 2. **Sandboxed pre-install scan** — when the cooldown has to be bypassed (CVE patch, fresh dep, urgent install), run the candidate tarball through a static-analysis scan that looks for the diagnostic signatures of supply-chain malware. The scan runs inside `bwrap`/`firejail`/`unshare` so a malicious package can't escape the inspection. 3. **`--ignore-scripts` at install** — postinstall is the #1 attack vector. Skip lifecycle scripts on every cooldown-bypass install.
These three together would have blocked the Mini Shai-Hulud TanStack attack on a stock laptop with no human in the loop.
Configure the cooldown
Verified config keys (npm v11+ and bun 1.3+):
| Manager | File | Key | Units | Exclusion key | |---|---|---|---|---| | npm | `~/.npmrc` (or project `.npmrc`) | `min-release-age` | days | none yet — proposed in [npm/cli#8994](https://github.com/npm/cli/issues/8994) | | bun | `~/.bunfig.toml` (or project `bunfig.toml`) | `[install] minimumReleaseAge` | seconds | `[install] minimumReleaseAgeExcludes = []` (exact names, no globs) |
Minimal config:
# ~/.npmrc
min-release-age=7
# ~/.bunfig.toml
[install]
minimumReleaseAge = 604800 # 7 days
minimumReleaseAgeExcludes = []
**Requires npm 11+.** Older npm silently ignores unknown keys, so the config looks correct but does nothing. Check with `npm --version` and `npm config get min-release-age` (should echo `7`, not `null`).
Per-command bypass
When the cooldown blocks an install you actually want:
npm install <pkg>@<version> --min-release-age=0 --ignore-scripts
bun add <pkg>@<version> --minimum-release-age=0 --ignore-scripts
The `bun add --minimum-release-age=0` CLI flag works in 1.3+ even though the docs don't list it — it follows bun's `bunfig key → kebab-case flag` convention.
**Always pair the bypass with `--ignore-scripts`.** Postinstall is the most common payload-execution path in supply-chain malware (Mini Shai-Hulud, event-stream, ua-parser-js, coa, all used it). Native modules that legitimately need postinstall can have the script run manually after a human-readable review:
(cd node_modules/<pkg> && cat package.json | jq .scripts) # eyeball it
(cd node_modules/<pkg> && npm run postinstall) # run if it checks out
When to scan before bypassing
The scan is for the dangerous moment: you've decided to bypass the cooldown and need a sanity check. The skill ships a reference script (`scripts/hotpatch.example.sh`) implementing the heuristics. Adapt it to your machine — Bash assumes `bwrap` (Linux); macOS users substitute `sandbox-exec` or skip the sandbox layer with the trade-off documented.
Static checks the scan should perform (each backed by a real attack):
| Check | Diagnostic of | Severity | |---|---|---| | `optionalDependencies` / `dependencies` containing `github:` or `git+` URLs | Mini Shai-Hulud (delivered payload via `github:tanstack/router#<sha>` ref) | RED | | Large JS file at package root not referenced by `main`/`module`/`exports`/`bin`/`files` | Planted payload pattern (`router_init.js` in Mini Shai-Hulud) | RED | | Unpacked size >3x the prior stable version | Bulk payload smuggling | RED | | `fileCount` delta of 1–4 paired with >2x size jump | Single planted file | RED | | `preinstall`/`install`/`postinstall`/`prepare` scripts present | Lifecycle-script attack vector (event-stream, ua-parser-js, etc.) | YELLOW | | JS files referencing `.ssh/`, `.aws/`, `.npmrc`, `GITHUB_TOKEN`, `AWS_SECRET`, kube config | Credential exfiltration | YELLOW | | Version flagged `deprecated` in npm registry with "security"/"compromised"/"malicious" wording | Maintainer/registry yank | RED | | OSV.dev returns known vulnerabilities for `<pkg>@<version>` | Disclosed CVE | RED (severity-dependent) |
**Why prerelease versions are skipped from the size-delta baseline:** dev/beta/rc versions have wildly different sizes than stable releases and produce false positives.
What the cooldown does *not* catch
Be honest about the limits with whoever you're configuring this for:
- **Old packages with new malicious versions still in the cooldown window are blocked**, but if the bad version *also* passes the cooldown (rare but possible — a compromise that goes >7 days undetected), the cooldown alone won't help. The scan catches most of those.
- **Transitive deps**. A clean `<pkg>` you install can pull in a compromised transitive. Defenses: scan against the *resolved* tree (`npm audit`, `osv-scanner`), and keep the cooldown active globally so transitive resolution also waits.
- **`npm ci`** against an existing lockfile. The cooldown applies during *resolution*, not installation of already-pinned versions. If your lockfile pins a compromised versio
Read more
name: supply-chain-hardening description: Configure install-time cooldowns for npm/bun (minimum release age) and run a sandboxed pre-install scan when the cooldown has to be bypassed. Use when the user asks about supply-chain attacks, npm/bun security, "minimum release age", a "cooldown" for installs, hardening against Shai-Hulud-class worms, or how to safely install a package that was just published. Also use after any recent supply-chain incident in the npm ecosystem.
Supply-chain hardening
Defends a journalism toolchain against the dominant npm/bun supply-chain attack pattern: a maintainer account or CI pipeline is compromised, a malicious version ships, and machines install it before anyone notices. Recent example: the **Mini Shai-Hulud TanStack attack (2026-05-11)** compromised 84 versions across 42 `@tanstack/*` packages and exfiltrated AWS / GCP / Vault / GitHub / SSH credentials via a postinstall script.
The defense is **layered** and intentionally simple:
1. **Install-time cooldown** — only install package versions older than N days (default 7). This is the primary defense. By the time the cooldown expires, the security community has almost always flagged a compromised version and the registry has yanked it. 2. **Sandboxed pre-install scan** — when the cooldown has to be bypassed (CVE patch, fresh dep, urgent install), run the candidate tarball through a static-analysis scan that looks for the diagnostic signatures of supply-chain malware. The scan runs inside `bwrap`/`firejail`/`unshare` so a malicious package can't escape the inspection. 3. **`--ignore-scripts` at install** — postinstall is the #1 attack vector. Skip lifecycle scripts on every cooldown-bypass install.
These three together would have blocked the Mini Shai-Hulud TanStack attack on a stock laptop with no human in the loop.
Configure the cooldown
Verified config keys (npm v11+ and bun 1.3+):
| Manager | File | Key | Units | Exclusion key | |---|---|---|---|---| | npm | `~/.npmrc` (or project `.npmrc`) | `min-release-age` | days | none yet — proposed in [npm/cli#8994](https://github.com/npm/cli/issues/8994) | | bun | `~/.bunfig.toml` (or project `bunfig.toml`) | `[install] minimumReleaseAge` | seconds | `[install] minimumReleaseAgeExcludes = []` (exact names, no globs) |
Minimal config:
# ~/.npmrc min-release-age=7
# ~/.bunfig.toml [install] minimumReleaseAge = 604800 # 7 days minimumReleaseAgeExcludes = []
**Requires npm 11+.** Older npm silently ignores unknown keys, so the config looks correct but does nothing. Check with `npm --version` and `npm config get min-release-age` (should echo `7`, not `null`).
Per-command bypass
When the cooldown blocks an install you actually want:
npm install <pkg>@<version> --min-release-age=0 --ignore-scripts bun add <pkg>@<version> --minimum-release-age=0 --ignore-scripts
The `bun add --minimum-release-age=0` CLI flag works in 1.3+ even though the docs don't list it — it follows bun's `bunfig key → kebab-case flag` convention.
**Always pair the bypass with `--ignore-scripts`.** Postinstall is the most common payload-execution path in supply-chain malware (Mini Shai-Hulud, event-stream, ua-parser-js, coa, all used it). Native modules that legitimately need postinstall can have the script run manually after a human-readable review:
(cd node_modules/<pkg> && cat package.json | jq .scripts) # eyeball it (cd node_modules/<pkg> && npm run postinstall) # run if it checks out
When to scan before bypassing
The scan is for the dangerous moment: you've decided to bypass the cooldown and need a sanity check. The skill ships a reference script (`scripts/hotpatch.example.sh`) implementing the heuristics. Adapt it to your machine — Bash assumes `bwrap` (Linux); macOS users substitute `sandbox-exec` or skip the sandbox layer with the trade-off documented.
Static checks the scan should perform (each backed by a real attack):
| Check | Diagnostic of | Severity | |---|---|---| | `optionalDependencies` / `dependencies` containing `github:` or `git+` URLs | Mini Shai-Hulud (delivered payload via `github:tanstack/router#<sha>` ref) | RED | | Large JS file at package root not referenced by `main`/`module`/`exports`/`bin`/`files` | Planted payload pattern (`router_init.js` in Mini Shai-Hulud) | RED | | Unpacked size >3x the prior stable version | Bulk payload smuggling | RED | | `fileCount` delta of 1–4 paired with >2x size jump | Single planted file | RED | | `preinstall`/`install`/`postinstall`/`prepare` scripts present | Lifecycle-script attack vector (event-stream, ua-parser-js, etc.) | YELLOW | | JS files referencing `.ssh/`, `.aws/`, `.npmrc`, `GITHUB_TOKEN`, `AWS_SECRET`, kube config | Credential exfiltration | YELLOW | | Version flagged `deprecated` in npm registry with "security"/"compromised"/"malicious" wording | Maintainer/registry yank | RED | | OSV.dev returns known vulnerabilities for `<pkg>@<version>` | Disclosed CVE | RED (severity-dependent) |
**Why prerelease versions are skipped from the size-delta baseline:** dev/beta/rc versions have wildly different sizes than stable releases and produce false positives.
What the cooldown does *not* catch
Be honest about the limits with whoever you're configuring this for:
- **Old packages with new malicious versions still in the cooldown window are blocked**, but if the bad version *also* passes the cooldown (rare but possible — a compromise that goes >7 days undetected), the cooldown alone won't help. The scan catches most of those.
- **Transitive deps**. A clean `<pkg>` you install can pull in a compromised transitive. Defenses: scan against the *resolved* tree (`npm audit`, `osv-scanner`), and keep the cooldown active globally so transitive resolution also waits.
- **`npm ci`** against an existing lockfile. The cooldown applies during *resolution*, not installation of already-pinned versions. If your lockfile pins a compromised versio
A collection of Agent Skills for journalists, researchers, academics, media professionals, and communications practitioners. The same repository serves Claude Code and Codex while keeping Claude-only commands, agents, and hooks clearly labeled.
Repo: jamditis/claude-skills-journalism
Other skills on claude-skills-journalism.
- /accessibility-compliance
Web accessibility patterns for news sites, journalism tools, and academic platforms. Use when building accessible interfaces, auditing existing sites for WCAG compliance, writing alt text for news images, creating accessible data visualizations, or ensuring content reaches all
Open skill - /claude-md-updater
Use this skill when the user asks to update CLAUDE.md, save a lesson, or persist something from the current session: phrases like "update claude.md", "what should we remember", "save this lesson", or "add to context". Scans the conversation for hard-won lessons, new file paths,
Open skill - /electron-dev
Electron desktop application development with React, TypeScript, and Vite. Use when building desktop apps, implementing IPC communication, managing windows/tray, handling PTY terminals, integrating WebRTC/audio, or packaging with electron-builder. Covers patterns from AudioBash,
Open skill - /mobile-debugging
Remote JavaScript console access and debugging on mobile devices. Use when debugging web pages on phones/tablets, accessing console errors without desktop DevTools, testing responsive designs on real devices, or diagnosing mobile-specific issues. Covers locally hosted Eruda and
Open skill - /one-way-door
Use this skill when creating new files that represent architectural decisions — data models, infrastructure configs, auth boundaries, API contracts, CI/CD pipelines, or event systems. Flags irreversible decisions and forces a discussion about trade-offs before committing.
Open skill - /python-pipeline
Python data processing pipelines with modular architecture. Use when building content processing workflows, implementing dispatcher patterns, integrating Google Sheets/Drive APIs, or creating batch processing systems. Covers patterns from rosen-scraper, image-analyzer, and
Open skill

