{"slug": "claude-code-skills-for-safe-php-and-js-package-updates", "title": "Claude Code Skills for safe PHP and JS package updates", "summary": "A developer created two Claude Code skills to enforce safe dependency update practices for JavaScript and PHP projects, addressing supply chain attack risks. The skills require agents to research recent security incidents, run registry audits, and enforce a seven-day minimum release age before installing any package updates. This approach aims to prevent compromised packages from reaching developer machines by waiting past the typical window when malicious versions are active and then yanked.", "body_md": "It's not abnormal for projects to go weeks, or dare I say months, between dependency updates. And when people finally do update, they do it in full force: everything at once, without checking anything.\n\nThat habit has always carried risk, but in the new world of AI agents doing the updating, it collides head-on with a very real threat: supply chain attacks.\n\n`install`\n\nis an arbitrary code execution feature\nThe package ecosystems we all depend on have spent the last few years demonstrating exactly how bad this can get. In September 2025, [ chalk and debug](https://www.wiz.io/blog/widespread-npm-supply-chain-attack-breaking-down-impact-scope-across-debug-chalk), part of a batch of eighteen packages with over two billion combined weekly downloads, started shipping a crypto-clipper after one maintainer's npm account was phished through a fake 2FA-reset email.\n\nDays later, the [Shai-Hulud worm](https://unit42.paloaltonetworks.com/npm-supply-chain-attack/) chewed through hundreds of packages on its own: its post-install script stole npm tokens from every machine it landed on and used them to publish more infected versions of itself. And a couple of weeks before either, the [Nx compromise](https://nx.dev/blog/s1ngularity-postmortem) put a post-install payload on developer machines that prompted locally installed AI coding CLIs like Claude and Gemini to hunt down wallets and credentials for exfiltration. That last one should make every agent owner sit up straight: our own agents, conscripted as burglars. The pattern is consistent: a malicious version goes live, does its damage for a few hours or days, then gets caught and pulled.\n\nBased on this, I decided, not to do updates till a set of rules have been met. These rules, I have decided to burn them into Claude skills and let my agents deal with them.\n\nIn Claude Code, a **skill** is just a markdown file with instructions the agent loads when a task matches. This gives me way to encode my hard-won paranoia *once* and have it applied *every single time*, by something that never gets tired, never gets sloppy on a Friday afternoon, and never thinks \"eh, it's probably fine.\"\n\nI wrote two of them, for now, `package-update-js`\n\nand `package-update-php`\n\none for my TypeScript projects, one for my Laravel PHP ones. They differ in tooling, but they encode the same worldview. These are the rules.\n\nThe first phase isn't an update at all. The agent has to research supply chain incidents from the last six months: compromised packages, typosquatting campaigns, and suspicious maintainer handovers (the exact vector behind [ event-stream](https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident) in 2018, when a helpful stranger offered to take over maintenance and then quietly shipped a bitcoin-wallet thief to two million weekly downloads). It cross-references those against the project's actual dependency list, and runs the registry's own audit (\n\n`composer audit`\n\n, the npm advisory data) on top. Every package gets a verdict: Only after that report exists does anything get updated.\n\nThis is the rule I'd tattoo on the ecosystem if I could: **never install a version that's less than seven days old.** Some package managers, like pnpm and Bun, have added support for a minimum release age to make it easy to enforce.\n\nCompromised releases are almost always short-lived. The poisoned `chalk`\n\nand `debug`\n\nversions were live for about two hours before npm pulled them. The malicious Nx releases lasted four. The malicious version ships, someone notices, it gets yanked. A release age gate means the poisoned window passes you by entirely. Every incident named above would have sailed past me without ever touching a machine, not because I'm vigilant, but because the versions would have been too young to install.\n\nIn my pnpm projects this is a single line in `pnpm-workspace.yaml`\n\n(the value is in minutes, so 10080 is seven days):\n\n```\nminimumReleaseAge: 10080\n```\n\nSince [pnpm 11](https://pnpm.io/supply-chain-security) you even get a one-day quarantine by default, and Bun has the same idea as `minimumReleaseAge`\n\nin `bunfig.toml`\n\n. Composer has no equivalent, so the PHP skill enforces it manually: it reads the release date of every candidate version and anything younger than seven days gets skipped and flagged as \"too fresh, revisit later.\"\n\nThere's one exception, and it cuts the other way: a release that fixes a known CVE goes through immediately, quarantine or not. A vulnerability you're currently running is a bigger risk than a version that's three days old.\n\nEvery Composer update runs with `--no-scripts`\n\n. Post-install scripts are the classic payload delivery mechanism that gives essentially full shell access, triggered automatically, on your machine. It's how Nx harvested SSH keys and wallets, and how Shai-Hulud found the npm tokens it used to spread.\n\nThe skill installs the package, lets verification happen, and only regenerates autoload and runs scripts after the update has been looked at.\n\nThe JS side is ahead of Composer here. pnpm refuses to run dependency build scripts unless you explicitly allowlist them, so my `pnpm-workspace.yaml`\n\nnames the only two packages allowed to execute anything at install time:\n\n```\nallowBuilds:\n  esbuild: true\n  sharp: true\n```\n\nEverything else gets installed but never runs. The same file sets `blockExoticSubdeps: true`\n\n, which stops transitive dependencies from sneaking in from random git repos or tarball URLs instead of the registry. Bun takes a similar stance and doesn't run lifecycle scripts for arbitrary dependencies by default.\n\nNo `^`\n\n, no `~`\n\n, no ranges. Every dependency is pinned to an exact version, and updates happen through explicit `composer require package:1.2.3`\n\nor `pnpm add package@1.2.3`\n\n, never through a blanket update command. My `pnpm-workspace.yaml`\n\nbacks this up with `savePrefix: \"\"`\n\n, which makes pnpm save exact versions instead of `^`\n\nranges by default. This does two things: it makes every version change visible in the diff (nothing drifts silently on the next lockfile regeneration), and it means the agent can never \"accidentally\" pull in something I didn't sign off on.\n\nThe skills forbid updating everything at once. Each package — or ecosystem group, since things like the Laravel core packages or the TanStack family have to move together — gets updated individually, followed immediately by verification: type checks for TypeScript, PHPStan plus the full test suite for PHP. If something breaks, we know exactly which update did it. Major versions are never applied without presenting the breaking changes and getting an explicit yes from me.\n\nHere's the thing that surprised me: the agent following these skills does updates *more* safely than I ever did by hand. I skipped changelogs when I was tired. I never once checked a package's release date before installing it. I definitely ran `composer update`\n\nwith scripts enabled my entire career.\n\nThe skill doesn't skip steps, because skipping steps isn't in the file. My updates happen every week now, and now the checks for attacks are delegated.\n\nYou can check out the [skills](https://github.com/neoighodaro/claude-skills) here.", "url": "https://wpnews.pro/news/claude-code-skills-for-safe-php-and-js-package-updates", "canonical_source": "https://dev.to/yulo/claude-code-skills-for-safe-php-and-js-package-updates-352a", "published_at": "2026-07-14 15:28:18+00:00", "updated_at": "2026-07-14 15:59:13.949056+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-safety"], "entities": ["Claude Code", "npm", "pnpm", "Bun", "Composer", "Chalk", "Debug", "Nx"], "alternates": {"html": "https://wpnews.pro/news/claude-code-skills-for-safe-php-and-js-package-updates", "markdown": "https://wpnews.pro/news/claude-code-skills-for-safe-php-and-js-package-updates.md", "text": "https://wpnews.pro/news/claude-code-skills-for-safe-php-and-js-package-updates.txt", "jsonld": "https://wpnews.pro/news/claude-code-skills-for-safe-php-and-js-package-updates.jsonld"}}