Use when reviewing dependency concerns: lockfile health, version pinning, immutable references, maintenance signals, transitive audit gates, monorepo version skew, reviewable lockfiles, license posture
How this skill is triggered — by the user, by Claude, or both
Slash command
/software-leverage-points:dependenciesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Dependencies are the part of the codebase the team did not write but ships anyway. Done well, the dependency graph reproduces deterministically, every reference is immutable, advisories are gated in CI, and license posture is documented. Done poorly, an unpinned transitive can change the build silently between two CI runs, and a moved tag can swap a maintainer without anyone noticing.
Dependencies are the part of the codebase the team did not write but ships anyway. Done well, the dependency graph reproduces deterministically, every reference is immutable, advisories are gated in CI, and license posture is documented. Done poorly, an unpinned transitive can change the build silently between two CI runs, and a moved tag can swap a maintainer without anyone noticing.
Core principle: The dependency graph is small, reproducible, reviewable, and audited. Provenance and integrity are joined; if you cannot answer where a dependency came from, you cannot answer whether it is safe to ship. Each dependency is presumed to need a justification, not the other way around: fewer, shallower trust relationships beat more, deeper ones, and lightweight entry points stay at zero.
A manifest declares the top of the graph; a lockfile pins everything beneath it. Without a committed lockfile, every install resolves the graph fresh, so two contributors (or two CI runs) install different transitive trees from the same manifest. Reproducibility, the precondition for both debugging and supply-chain auditing, is gone.
Multiple valid pinning styles exist: exact pins on direct dependencies, or ranges-with-lockfile. The principle is: the resolved graph reproduces deterministically. The red flag is "graph does not reproduce," not "did not pin every direct dep to an exact version."
Multiple valid lockfile-commit policies exist: always-committed (the conventional default), or CI-generated and verified. Either is defensible; pick one and apply it consistently.
Caret, tilde, or wildcard ranges on direct dependencies in an ecosystem with no committed lockfile mean a transitive change in any sub-dependency can ship to production without anyone noticing. A floating range plus no lockfile turns external maintainers into uncredentialed committers on your build.
This principle scopes to anything the project pulls from outside its own repo where the reference can be moved server-side: dependencies from a git URL or tarball URL, GitHub Actions in CI, container base images, and submodules. When the scope applies: pin to an immutable reference (a commit SHA, a content digest), not a tag or branch.
A tag can be moved. A branch certainly can. The XZ-utils backdoor (CVE-2024-3094, 2024) demonstrated the tag-repointing path against a CI Action: a maintainer with social-engineered trust silently moves the tag, and every repo using the tag executes attacker code on the next push with no diff in their own repository. The same mechanism applies to git+https://...#main, to FROM debian:stable, and to git submodule references that track a branch.
# SAFE: SHA cannot be repointed; an update produces a reviewable diff.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
# UNSAFE: tag can be moved server-side overnight.
- uses: actions/checkout@v4
Cross-reference: the continuous-delivery skill carries the gate-enforcement side; this skill carries the immutable-reference shape that makes the gate trustworthy.
A direct dependency whose upstream has had no release in two years, is archived, has a single maintainer who has gone silent, or whose homepage 404s is a CVE incubator and a future incident. Trust shifts in projects whose maintenance signals have already degraded; the historical record is consistent on this point. Cross-reference: the purpose-and-scope skill carries the upstream check on whether the dependency belongs in the project at all, which precedes the maintenance-signal check this skill carries.
The bulk of vulnerabilities reachable from an application live in transitive dependencies the team never directly chose. A CI step that scans the resolved tree against an advisory database is non-negotiable for any project past the prototype stage. Without an audit gate, vulnerabilities accumulate silently between scans.
This principle scopes to projects with CI; cross-reference the security skill for the runtime-CVE side of the same gate, and the continuous-delivery skill for the gate-enforcement and pinned-action discipline that makes this audit step a reviewed and trustworthy step of the pipeline.
This principle scopes to monorepos and workspace-style projects. When the scope applies: a given dependency resolves to a single version across all workspace packages. Version skew inside a single deployable unit means two copies of the same library ship together, doubling attack surface and silently changing behavior at module boundaries. Drift here also defeats license-audit and CVE tooling, which assumes one resolved version per name.
A lockfile is a code-review artifact: a reviewer must be able to tell whether a PR is bumping one patch version or quietly swapping a maintainer. Binary-only lockfiles save bytes but make the supply chain opaque to code review; a four-line dependency change and a four-thousand-line one look identical in git diff.
This principle scopes to ecosystems that admit binary lockfiles; in ecosystems with text-only lockfiles it is satisfied by construction. Where the scope applies, commit a paired text-format lockfile alongside the binary one.
License obligations are contractual; a copyleft transitive in a closed-source product can force disclosure or relicensing. A license audit step in CI, plus a documented allowlist or denylist, makes the obligation explicit. Provenance and licensing are joined: the same posture that answers "where did this come from" answers "are we allowed to ship it."
Newly published versions of any dependency carry the highest probability of malicious or broken content per unit time. Account-takeover attacks, postinstall payloads, and accidental releases concentrate in the first hours-to-days after publish, before the wider ecosystem has a chance to surface advisories. A cooldown window (a hold of 48 hours to 1 week before a new version is allowed to land in the lockfile) buys the project the benefit of the rest of the ecosystem's scrutiny without writing any of it.
The mechanism is a constraint on the dependency-update bot, not a manual gate: Renovate's minimumReleaseAge, Dependabot's cooldown, or an equivalent. The constraint applies to every direct and transitive dependency, not just the ones the team thinks are risky. The litellm 1.82.8 incident (2026) and the Shai-Halud campaign (2025) both compromised packages where versions inside the cooldown window would have been quarantined long enough for the malicious release to be yanked before any production install picked it up.
A cooldown is not a substitute for the audit gate (principle 5); it is a multiplier on it. The audit catches what is known; the cooldown buys the time during which an unknown becomes a known.
Every dependency is a trust relationship; every transitive dependency is a trust relationship the team did not explicitly agree to. The durable answer to most dependency-related risk is fewer dependencies, not better ones, and shallower trees rather than deeper ones.
Heuristics that make this principle operational:
syntropic137-npx setup package enforces a strict zero-dependency rule for exactly this reason. Cross-reference: the developer-experience skill carries the single-command-onboarding stance that makes setup CLIs valuable in the first place; the supply-chain stance here is what keeps that command trustworthy.pnpm why <package>, uv tree --depth 3, and equivalents make the tree visible. Any dependency that visibly inflates the tree should earn its keep; if the choice is between two libraries with similar value, the one with the smaller blast radius wins.This principle is not a vow of poverty; large, well-maintained dependencies (frameworks, runtimes, ORMs) earn their place. It is the default stance: each dependency is presumed to need a justification, and the justification is the question, not the answer. See dependency-minimization/README.md for the heuristics worked through with examples.
Where a project commits to a specific minimization rule (zero runtime dependencies for a setup CLI, maximum transitive depth of N for a library, a hard cap on transitive count), the rule is enforced as a fitness function in CI: a script that fails the build when the rule is violated. A commitment that is not mechanically checked is not a commitment, only an aspiration; the fitness-function move is what keeps the surface from drifting one PR at a time. Cross-reference: see the architecture skill's fitness-functions deep-dive for the broader framing; this skill carries the dependency-specific instances.
Several ecosystems execute third-party code as part of installing or importing a package, before any of the project's own code runs. Each is a path by which a poisoned transitive can run arbitrary code with the privileges of the installing or importing user, including CI's secret-bearing token.
postinstall and preinstall hooks run on every package in the tree by default. A blanket block (npm ci --ignore-scripts) is right for projects that do not need native binaries. Where native binaries are legitimate (esbuild, sharp), an explicit allowlist (pnpm's onlyBuiltDependencies) is the smaller, auditable surface..pth files placed in site-packages execute on interpreter startup, before any import. The litellm 1.82.8 attack used this path, which --ignore-scripts does not address (it is a Python runtime feature, not an install hook). The defense is hash verification (principle 12) and dependency minimization (principle 10), which together reduce the probability that a poisoned package reaches site-packages at all.__init__.py injection runs on first import. Same defense set.Block-by-default is the rule; per-package exceptions are explicit and reviewed. The cost of a one-line review on a new exception is much smaller than the cost of one undetected postinstall payload reaching CI.
Cross-reference: the security skill carries the runtime-CVE and secrets-exposure side of supply-chain risk; this skill carries the install-time-execution side.
A version pin alone says "the resolver picked the artifact named X.Y.Z." It does not say "the bytes I am installing are the bytes that were reviewed when that version was added to the lockfile." If a package registry is compromised and the artifact for an existing version is replaced with a malicious one, version-only pinning installs the new bytes without complaint.
Hash verification closes that gap. Most modern lockfiles already record content hashes (go.sum, Cargo.lock, npm's package-lock.json, pnpm's pnpm-lock.yaml); the discipline is to use the lockfile-honouring install command (npm ci, pnpm install --frozen-lockfile, cargo build --locked, go mod download with GOFLAGS=-mod=readonly) and to fail closed if the hash does not match. For Python, uv export --hashes plus pip install --require-hashes provides the equivalent integrity check; without --require-hashes, missing hashes silently fall back to unverified installs.
Where the registry serves over HTTPS to a trusted certificate authority, the typical attack is not in transit; it is at the registry itself. Hash verification defends against both. Cross-reference principle 1 (lockfiles pin what the manifest does not): the hashes belong in the same lockfile that pins the version.
Cross-reference: the developer-experience skill consumes the setup-CLI / bootstrap pattern this skill documents (the syntropic137-npx zero-runtime-dep example), pairing the supply-chain stance with the single-command-onboarding stance for end-user-facing setup surfaces.
latest rather than commit SHA or content digestminimumReleaseAge window)npm install / pnpm install in CI without --ignore-scripts or a reviewed onlyBuiltDependencies allowlistpip install rather than pip install --require-hashes against a hashed export, so a compromised PyPI artifact at a pinned version installs silentlyLICENSES.md or equivalent posture document; copyleft transitive shipped into a proprietary product without legal review| Excuse | Reality |
|---|---|
| "The manifest is the lockfile" | It is not; a manifest declares the top of the graph, the lockfile pins the rest |
| "We'll add the audit gate later" | Vulnerabilities accumulate between scans; later is not free |
| "The tag won't move" | Tags move; the historical record agrees |
| "The package hasn't been updated because it's stable" | Stable and unmaintained look identical from the outside; the difference is whether a patch ships if needed |
| "Version skew in the monorepo is harmless" | Two copies double the attack surface and break audit tooling |
| "The binary lockfile is fine; trust the diff" | Reviewers cannot review what they cannot read |
| "Licenses are a legal problem, not an engineering one" | The obligation is engineered when the dependency lands; legal can only triage what engineering exposes |
| "We need the latest version the day it ships" | The first 48 hours of a release are when malicious or broken content is most likely; the cost of waiting a week is much smaller than the cost of catching a poisoned release |
| "Just one more dependency for this small thing" | Each dependency is a trust relationship that compounds; the AI-era cost of writing the small thing is much lower than the lifetime cost of trusting a transitive tree |
| "We can't avoid postinstall hooks; we have native deps" | Allowlist the specific packages that need build steps; do not leave the door open for every transitive |
| "Version pinning is enough" | A registry compromise can serve different bytes for the same version; hash verification is the integrity check version pinning does not provide |
| "Fewer dependencies means reinventing the wheel" | Large, well-maintained dependencies earn their place; the principle is the default stance, not a vow of poverty |
| "We agreed on a zero-dep rule; everyone knows" | Without a CI fitness function checking the rule, the next contributor adds a dep with no review prompt and the rule is gone |
✅ Manifest + committed lockfile; clean install on a fresh machine reproduces the tree
❌ Manifest only; every install resolves fresh; transitive drift ships silently
✅ "foo": "^1.2.3" with a committed lockfile pinning the resolved subtree
❌ "foo": "*" or "^1" with no lockfile
✅ git+https://example.com/repo#abcdef0123456789... (immutable commit SHA)
❌ git+https://example.com/repo#main (branch, mutable)
✅ CI step: audit gate scans the resolved tree on every PR
❌ Audits run quarterly by hand, if at all
✅ Monorepo: [email protected] across all workspace packages
❌ pkg-a uses [email protected]; pkg-b uses [email protected]; no stated reason
✅ Binary lockfile committed alongside text-format counterpart for review
❌ Only the binary lockfile is committed; PR diffs are opaque
✅ License allowlist enforced in CI; LICENSES.md tracks transitive license posture
❌ Licenses unaudited; first awareness of a copyleft transitive is in legal review
✅ uses: actions/[email protected] # v4 (immutable SHA)
❌ uses: actions/checkout@v4 (mutable tag; XZ-utils path)
✅ Renovate / Dependabot configured with minimumReleaseAge of 7d
❌ Bot lands every new version the hour it publishes
✅ Setup CLI / install script ships with zero runtime dependencies
❌ "Lightweight" entry point pulls in a 200-package transitive tree
✅ CI fitness function fails the build when package.json adds a runtime "dependencies" entry
❌ Zero-dep rule documented in CONTRIBUTING.md, never mechanically enforced; decays one PR at a time
✅ Adopt zod (zero transitives) over a similar library that pulls 50+
❌ Pick the first hit on the ecosystem search, accept whatever transitives come
✅ npm ci --ignore-scripts; pnpm install with explicit onlyBuiltDependencies allowlist
❌ npm install in CI; every transitive's postinstall hook runs in the secret-bearing job
✅ uv export --hashes ... | uv pip install --require-hashes
❌ pip install (no hashes); a registry-compromised artifact for a pinned version installs silently
Dependencies are where the supply chain meets the codebase. The cost of getting them wrong is paid in incidents (a moved tag, an unpublished package, a malicious update), in compliance exposure (a copyleft transitive in a SaaS), and in slow erosion (CVEs accumulating between manual scans).
Without disciplined dependency management:
With disciplined dependency management:
Soft sketch; not a checklist. Where appropriate is shaped by the target's maturity.
--require-hashes or equivalent); immutable references for every external source including CI Actions; advisory-database scan on every PR; install-hook allowlist explicit; cooldown window enforced; license allowlist enforced; monorepo version-skew detection in CI.security skill for runtime-CVE handling.--require-hashes is the discipline that makes a registry compromise at a pinned version detectable.architecture skill's fitness-functions deep-dive. Backs the enforcement clause of principle 10. A minimization rule is an architectural characteristic of the project; the same fitness-function discipline that keeps coupling and dependency direction enforced keeps zero-dep and tree-depth rules enforced.These go stale fast; the date is the "as-of." Verify currency before adopting. The principles above outlast specific tools; if a tool here is no longer maintained, the patterns transfer to its replacement.
npm audit, pnpm audit, yarn audit, or bun audit for advisory scanning; license-checker for license audits; bun.lock (text) committed alongside bun.lockb (binary) for reviewable lockfiles.pip-audit for advisory scanning; pip-licenses for license inventory; lockfiles via poetry, uv, pdm, or pip-tools (requirements.txt with hashes).cargo audit (advisory database), cargo deny (license + advisory + duplicate detection); Cargo.lock always committed for binaries, optionally for libraries.go mod with go.sum for resolved hashes; govulncheck for advisory scanning; go-licenses for license inventory.dependency-locking.minimumReleaseAge window of at least several days, and to surface upgrades for human review rather than auto-merging.gh api repos/<owner>/<repo>/git/ref/tags/<tag>; OSV Scanner action; dependency-review-action for PR-time gating; OpenSSF Scorecard for upstream posture signals.npm ci --ignore-scripts, pnpm onlyBuiltDependencies allowlist in package.json, yarn --ignore-scripts. For Python, awareness that --ignore-scripts does not exist; the equivalent defenses are hash verification, dependency minimization, and isolation (pinned interpreter, ephemeral CI environment).pnpm why <package>, npm ls, uv tree --depth N, cargo tree, go mod graph. deptry (Python) and depcheck (Node) for unused-dependency detection.uv export --hashes plus uv pip install --require-hashes for Python; npm ci (uses package-lock.json integrity field); pnpm install --frozen-lockfile; cargo build --locked; go mod download with GOFLAGS=-mod=readonly.This skill is maintained at: https://github.com/syntropic137/software-leverage-points/blob/main/skills/dependencies/SKILL.md
To improve it, edit the file directly and follow the chassis discipline in maintaining-software-leverage-points: regenerate catalogs, run just qa, then commit.
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub syntropic137/software-leverage-points --plugin software-leverage-points