> Supply-chain security baseline for AI-assisted development — from The Handover, the-handover.org/docs/supply-chain-baseline-ai-development > Authors: Leon Mallett (captivated.online) with Claude Code · Last confirmed working: 2026-08-07 > © Captivated Ltd — free to use in your own work, not to redistribute as a collection. the-handover.org/licence AI coding assistants install and update dependencies, which is the single richest supply-chain attack surface they touch. Malicious package versions run install-time hooks that scrape credentials, enumerate cloud metadata, inject configuration for assistants to execute, and exfiltrate to attacker infrastructure. You cannot un-run a hook or un-leak a credential. Rotation is the only remedy afterwards. So the entire discipline is **caution before install**: pin, cool off, and do not run lifecycle scripts you have not reasoned about. This is a baseline. A project with its own security policy overrides it. ## What the threat actually looks like Worth stating concretely, because the abstract version invites complacency: - **Compromise reaches "trusted" scopes.** An attacker who compromises an upstream CI/CD pipeline rather than a maintainer account can poison an entire reputable, scoped namespace at once. A recognised organisation name is not a safety guarantee. - **Install hooks are the payload delivery mechanism.** `preinstall`, `install`, `postinstall` and `prepare` scripts run automatically, with your user's permissions, before you have looked at anything. - **CI runners are the highest-value target.** Privilege escalation on the runner, scraping runner memory for secrets, and exchanging federated identity tokens for registry tokens all happen there rather than on a laptop. - **Assistant configuration is an injection point.** Payloads staged under assistant config directories exist specifically so that an agent will read and act on them. - **Exfiltration masquerades as legitimate traffic**, including as calls to lookalike AI-provider endpoints. Package registries for JavaScript see the highest volume, but the same patterns reach every ecosystem. ## Before adding or updating any dependency 1. **State the exact package name and version** you intend to install. 2. **Check when it was published** — most registries expose publication times. 3. **Flag anything released in the last 72 hours** and require explicit confirmation before installing. This window is what catches a freshly poisoned release. 4. **Note any lifecycle scripts** the package declares. 5. For unfamiliar packages, cross-reference a package-risk service or the relevant advisory database. 6. **Wait for explicit confirmation** before running the install. 7. **Prefer lockfile-respecting commands** — the install command that honours the lockfile exactly, rather than the one that resolves afresh. ## When auditing existing dependencies Read the manifests. List direct dependencies with versions and run the ecosystem's audit tool. Compare against recent compromised-package lists. Look for recently-modified files inside installed dependency trees, and report findings **before** taking any further action. ## Never modify without explicit approval and a shown diff These are high-value injection points: - Environment and secret-bearing files - Shell startup files - Git hooks and git configuration - CI/CD workflow configuration - AI-assistant configuration directories, and agent instruction files - **Lockfiles** — always show the diff first ## Stop and alert immediately on - Unexpected files in assistant configuration directories - Lifecycle scripts making network calls or performing file I/O - Sudden major version bumps with minimal or missing changelogs - Dependencies that appeared without anyone requesting them - New or modified git remotes - Obfuscated, minified or base64-encoded code inside source dependencies - Packages reading environment variables unrelated to their stated purpose - Unfamiliar repositories referenced in webhook URLs or package metadata ## Ecosystem notes **JavaScript package managers** carry the highest risk. A committed configuration file that disables lifecycle scripts by default neutralises install-hook credential stealers — most dependencies obtain native binaries through optional platform packages and need no scripts at all. Pinning exact versions rather than ranges means a poisoned patch release cannot be pulled in automatically. A dependency that genuinely needs a build step should be rebuilt explicitly, which is a useful moment to ask why. **Compiled-language package managers** — commit the lockfile, run the ecosystem's audit tool regularly, and check maintainer history and release recency for unfamiliar crates or modules. **Python** — install against hashes where possible, watch for typosquatted names, and pin locked versions. **Platform dependency managers for mobile and desktop** — commit the resolved manifest, verify it is unchanged, and confirm resolved sources match the expected repositories. **Hybrid desktop frameworks** have two supply chains, native and scripted. Audit both. Build-time dependencies run with elevated trust and deserve extra scrutiny. ## CI hardening The runner is the prime target, so harden it from the first commit: - Least-privilege permissions by default, read-only unless a job needs more. - **Pin actions by full commit hash, not by tag.** A tag can be moved. - Use the lockfile-exact install command, with lifecycle scripts disabled. - **No long-lived tokens.** Prefer short-lived federated credentials, scoped to a single job. - Never expose secrets to builds triggered by forks. - Prefer ephemeral runners over persistent self-hosted ones carrying ambient cloud credentials. Treat a CI configuration change arriving inside a dependency-update pull request as a red flag on its own. ## Why this belongs in an agent's context An agent that installs a package is making a trust decision on the operator's behalf, usually faster than the operator can review it, and usually while focused on something else. The rules above are not about distrusting the agent. They are about putting the pause in a place where a human can still use it — before the install, rather than after the hook has run.