Install
$ agentstack add skill-carlkibler-agent-skills-dependency-pinning ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Dependency Pinning
A dependency safety scan — not a CVE scan. It checks two things across every ecosystem in scope:
- Pinning — dependencies pinned to an immutable content SHA / digest, not a
movable tag. Tags can be silently re-pointed to altered or malicious artifacts (the tj-actions class of supply-chain attacks). A digest can't.
- Cooldown — a project never adopts an artifact newer than N days (default
7). A fresh release is where a compromise lands first; the cooldown buys time for it to be caught before it reaches the build.
Report first. Mutate only on explicit approval. Bumping a pin is itself risky, so every proposed change names the new SHA and flags it for a supply-chain check.
Scope
Ask what to scan if unclear: a single project, a list of repos, or "everything under ~/dev/work". Then discover dependency manifests:
ROOT="${1:-.}"
/usr/bin/find "$ROOT" -type d \( -name node_modules -o -name .git -o -name .terraform \
-o -name vendor -o -name packages -o -name bin -o -name obj -o -path '*/assets/libs' \) -prune -o \
-type f \( \
-iname 'Dockerfile*' -o -name 'docker-compose*.y*ml' -o -name 'compose*.y*ml' \
-o -path '*/.github/workflows/*.y*ml' \
-o -name 'package.json' -o -name 'deno.json*' \
-o -name 'pyproject.toml' -o -name 'requirements*.txt' \
-o -name '*.csproj' -o -name 'packages.config' -o -name 'Directory.Packages.props' \
-o -name 'Cargo.toml' -o -name 'go.mod' \
-o -name 'pom.xml' -o -name 'build.gradle' -o -name 'build.gradle.kts' \
-o -name 'Gemfile' -o -name '*.gemspec' \
-o -name '*.tf' \
\) -print 2>/dev/null
# Also catch images pulled from scripts/CI, not just Dockerfiles/compose:
grep -rEn 'docker (run|pull|build)[^|]*[a-z0-9./-]+:[a-z0-9._-]+' "$ROOT" \
--include='*.sh' --include='*.y*ml' --include='Makefile' 2>/dev/null
Ignore vendored/minified asset trees (*/assets/**, *.min.*) — those package.json files are bundled libraries, not your declared dependencies.
What "good" looks like, how to detect violations, how to fix
Docker / Compose (pinning: required · cooldown: manual)
- Good:
FROM repo/img@sha256:·image: repo/img@sha256: - Bad:
:latest, floating tags, no digest. - Detect:
grep -rEn '^\s*FROM |image:\s'→ flag any ref without@sha256:.
Also scan scripts/CI/Makefiles for docker run|pull|build ... img:tag — images pulled outside Dockerfiles/compose are easy to miss and just as swappable.
- Fix: resolve the digest of a tag that is ≥ N days old:
docker buildx imagetools inspect repo/img: --format '{{.Manifest.Digest}}' then write repo/img@sha256: # .
- Cooldown: no native support — enforce by choosing a digest for an old-enough tag.
GitHub Actions (pinning: required · cooldown: via tooling)
- Good:
uses: owner/repo@ # vX.Y.Z - Bad:
@v4,@main,@. - Detect:
grep -rEn 'uses:\s' .github/workflows→ flag any ref not matching a 40-char hex SHA. - Fix:
git ls-remote https://github.com// refs/tags/→ SHA; pin with the version in a trailing comment. - Cooldown / automation:
ratchet(sethvargo/ratchet) orpinactpin+update actions by SHA;
Renovate/Dependabot minimumReleaseAge / cooldown gates the version that gets pinned.
JavaScript — npm / yarn / pnpm / bun / deno (pinning: lockfile · cooldown: tooling)
- Good: lockfile committed (
package-lock.json/yarn.lock/pnpm-lock.yaml/
bun.lock / deno.lock) with integrity hashes, and CI installs frozen (npm ci, pnpm i --frozen-lockfile, yarn --immutable, deno install --frozen).
- Bad: no lockfile committed; relying on
^/~/latestwithout a lock;npm installin CI. - Detect: manifest present but lockfile missing/gitignored; CI using non-frozen installs.
- Fix: generate + commit the lockfile; switch CI to the frozen install command.
- Cooldown: pnpm has native
minimumReleaseAge(config/.npmrc). For npm/yarn/bun,
add Renovate minimumReleaseAge: "7 days" (or Dependabot cooldown). Deno: pin exact versions in import map / deno.json; deno.lock carries integrity.
Python — uv / pdm / poetry / pip (pinning: lockfile+hashes · cooldown: uv native / tooling)
- Good: lockfile committed with hashes (
uv.lock,pdm.lock,poetry.lock) and
installed locked (uv sync --locked, pdm sync, poetry install); for bare pip, hashed pins via pip-compile --generate-hashes + pip install --require-hashes.
- Bad: unpinned/
>=/*requirements, no lockfile, no hashes. - Detect:
pyproject.toml/requirements.txtpresent but no lockfile/hashes; ranges without a lock. - Fix: adopt a lock workflow or generate hashed requirements; commit the lock.
- Cooldown: uv has native
exclude-newer/UV_EXCLUDE_NEWER(resolve as of a date —
a true cooldown). Otherwise Renovate minimumReleaseAge.
.NET — NuGet (pinning: exact versions + lockfile · cooldown: tooling)
- Good: exact versions (
packages.configversion="x.y.z", or `with no range/) **plus a committedpackages.lock.json`*
(enable true, restore with dotnet restore --locked-mode). The lockfile carries contentHash per package.
- Bad: floating versions (
Version="*",Version="[1.0,)"), no lockfile, packages
restored from a non-pinned feed.
- Detect:
grep -rEn 'Version="\*"|Version="\[' **/*.csproj;.csproj/packages.config
present but no packages.lock.json beside it; check Directory.Packages.props for central versions if used.
- Fix: pin exact versions; enable + commit
packages.lock.json; pin the feed in
nuget.config.
- Cooldown: no native NuGet cooldown — use Renovate
minimumReleaseAge(NuGet supported).
Rust — Cargo · Go · Java (Maven/Gradle) · Ruby (Bundler)
Terser, but the same two questions apply (immutable pin? cooldown?):
- Rust/Cargo: commit
Cargo.lock(carries crates.io sha256 checksums);cargo --locked.
No native cooldown → Renovate minimumReleaseAge (cargo datasource). cargo audit/cargo vet adjacent.
- Go modules:
go.mod+go.sum(cryptographic hashes, verified vs the checksum DB);
go mod verify, build with -mod=readonly. No native cooldown → Renovate (gomod).
- Java/Maven: pin exact versions in
pom.xml— banLATEST/RELEASE/version ranges
(enforce with maven-enforcer requireReleaseDeps / ban-dynamic-versions). No lockfile natively.
- Java/Gradle: enable dependency locking (
gradle.lockfile) + verification metadata
(gradle --write-verification-metadata sha256 → verification-metadata.xml with checksums/signatures).
- Ruby/Bundler: commit
Gemfile.lock;bundle config set frozen true; add checksums with
bundle lock --add-checksums (Bundler 2.5+). No native cooldown → Renovate (bundler).
- Cooldown across all of the above is best delivered by Renovate
minimumReleaseAge/
Dependabot cooldown, which support these datasources.
Any other ecosystem you encounter (general rule)
Don't stop at the languages listed here. For any package manager in the target:
- Identify the manifest + its lockfile; confirm the lockfile carries **integrity
hashes and is committed, and that CI installs frozen/locked**.
- Flag floating/range/
latestversion specifiers in the manifest. - Research whether that manager supports a cooldown — native settings first
(names vary: minimumReleaseAge, exclude-newer, --as-of, min-age, quarantine), then a meta-tool (Renovate minimumReleaseAge / Dependabot cooldown) for that datasource. If unsure, check the tool's current docs rather than guessing.
- Report findings the same way and propose the concrete setting to add.
Terraform (pinning: lock + version constraints)
- Good:
.terraform.lock.hclcommitted with multi-platform hashes
(terraform providers lock -platform=linux_amd64 -platform=darwin_arm64 ...); providers pinned in required_providers; modules pinned by version or git commit SHA; AMIs/data sources pinned by ID (no most_recent = true).
- Bad: lock gitignored, missing platforms,
most_recent = true, modules onmain. - Detect: lock in
.gitignore;grep -rn 'most_recent\s*=\s*true' *.tf; module sources on a branch. - Fix: un-ignore + commit the lock (multi-platform); pin module/AMI refs.
Adding cooldowns where supported (offer these)
- Renovate (cross-ecosystem):
"minimumReleaseAge": "7 days"inrenovate.json— the
single best lever; gates npm/pip/docker/actions/etc. behind the cooldown.
- Dependabot:
cooldown:block in.github/dependabot.yml. - pnpm:
minimumReleaseAge· uv:exclude-newer· GH Actions: ratchet/pinact.
Report format
DEPENDENCY SAFETY REPORT (cooldown target: 7 days)
===================================================
Docker : 2 images unpinned (FROM node:20, postgres:16) — PIN MISSING
GH Actions : 3 actions on tags (@v4) — PIN MISSING
JS (pnpm) : lockfile committed ✓ · no cooldown — COOLDOWN MISSING
Python (uv) : uv.lock ✓ · exclude-newer not set — COOLDOWN MISSING
Terraform : .terraform.lock.hcl gitignored — LOCK NOT COMMITTED
...
SUMMARY: 4 pin gaps, 3 cooldown gaps, 1 uncommitted lock across N repos.
Classify each as: OK · PIN MISSING · COOLDOWN MISSING · LOCK NOT COMMITTED. Then list exact fixes (the resolved SHA/digest, the config snippet) per item.
Action rules
- Default to read-only. Do not edit files, run installers, or commit until the user approves.
- When approved, change one ecosystem at a time; show the diff.
- Every pin bump names the new SHA/digest and reminds the user to do a supply-chain
check and respect the cooldown (no artifact newer than N days).
- Never weaken an existing pin. Never add a
:latest/floating ref as a "fix". - Keep the human-readable version in a trailing comment beside every SHA pin.
- Commit lockfiles — never gitignore them.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: carlkibler
- Source: carlkibler/agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.