claude-jacked is published to PyPI, used as a developer-tool dependency, and ships behavioral rules + hooks that Claude Code installs into users' shells.
That blast radius makes the publish pipeline the highest-value target in this repo. The pipeline currently passes core dependency-integrity checks
(uv.lock has SHA-256 hashes; pip-audit reports zero vulnerabilities; PyPI Trusted Publishers
eliminates long-lived PYPI_API_TOKEN exposure), but four high-risk patterns remain:
pypa/gh-action-pypi-publish is tag-pinned, not SHA-pinned — a tag-mutation attack (tj-actions class) would publish poisoned wheels to PyPI under claude-jacked's name.step-security/harden-runner egress filtering — a compromised dep installed during build could exfil to anywhere unobserved.persist-credentials: false on checkout — GITHUB_TOKEN persists in .git/config and the artifact upload step uploads dist/ only (low actual risk) but the pattern is still wrong.id-token: write is overly broad — should be on the publish job only, not the build job.
None of these have been exploited here; all are pre-emptive. The audit also flags a number of monitoring gaps
(Dependabot, SBOM, pre-commit secret scanning, in-CI workflow lint) that have not caused harm but would catch future regressions.
/lockdown fix can apply most of these as low-risk auto-fixes.
| Band | Score | Posture |
|---|---|---|
| Hardened | 90–100 | Gold-standard supply-chain hygiene. |
| Solid baseline | 70–89 | Most controls present; minor gaps. |
| Critical gaps | 50–69 | Important controls missing; address before next release. |
| Significant exposure | 0–49 | Hardening is the next blocker. ← you are here |
Per-category status — where to focus, vs. the overall number above.
| Category | Status | Notes |
|---|---|---|
| Lockfile integrity | ok | uv.lock committed with SHA-256 on 68 packages; uv lock --check reproduces clean |
| Dependency CVEs | ok | pip-audit via OSV: no known vulnerabilities; osv-scanner not installed (would be 2nd opinion) |
| Malware / typosquat | warn | Socket CLI not installed; no install-script heuristic findings on this Python-only repo |
| CI/Actions hardening | danger | 5 unpinned actions (1 critical: PyPI publisher), excessive workflow permissions, missing persist-credentials, no Harden-Runner. Primary problem area. |
| Secrets hygiene | ok | .gitignore covers all common secret patterns; no hardcoded secrets in tree; gitleaks not installed (would be CI gate) |
| Provenance & signing | warn | PyPI Trusted Publishers (OIDC) active — long-lived tokens eliminated. No SBOM generated per release. No PEP 740 attestations. |
| Container hardening | n/a | No Dockerfile |
| Pre-commit + Scorecard | warn | No .pre-commit-config.yaml; OpenSSF Scorecard not running |
| Ecosystem | Detected | Scanner | Result |
|---|---|---|---|
| Python (uv) | pyproject.toml, uv.lock | pip-audit 2.x via OSV | no known CVEs |
| Python (uv) — lockfile integrity | uv.lock (68 packages) | uv lock --check + hash count | hashes present |
| GitHub Actions | .github/workflows/publish.yml | zizmor 1.24.1 | 5 errors, 1 warning |
| Secrets in git | .gitignore coverage | grep heuristic (gitleaks missing) | .gitignore covers all common patterns |
| Node.js | — | — | not present |
| Docker / container | — | — | not present |
| OpenSSF Scorecard | — | scorecard CLI missing | not measured |
| Socket (malware/typosquat) | — | socket CLI missing | not measured |
| OSV-Scanner (second opinion) | — | osv-scanner missing | not measured |
pypa/gh-action-pypi-publish@release/v1 is not SHA-pinned
.github/workflows/publish.yml:51uses: pypa/gh-action-pypi-publish@release/v1release/v1 to a malicious commit. Every consumer using this tag would then run attacker code with OIDC id-token permission and direct PyPI publish authority — they could ship a poisoned claude-jacked wheel to PyPI without your knowledge. This is exactly the tj-actions CVE-2025-30066 attack pattern, applied to your release pipeline.gh api repos/pypa/gh-action-pypi-publish/git/refs/tags/v1.13.0. Replace with: uses: pypa/gh-action-pypi-publish@<sha> # v1.13.0. Set up Dependabot or Renovate with a 7-day cooldown to keep the SHA fresh while still gaining tag-mutation immunity.true — /lockdown fix can pin via pinact run --min-age 7actions/*) not SHA-pinned
.github/workflows/publish.yml:15, 18, 31, 45uses: actions/checkout@v4
uses: actions/setup-python@v5
uses: actions/upload-artifact@v4
uses: actions/download-artifact@v4pinact run will do all four in one pass.trueid-token: write is overly broad
.github/workflows/publish.yml:7–9permissions:
contents: read
id-token: writeid-token: write — only the publish job does. Granting OIDC token-mint capability to a job that runs python -m build means a malicious dep can mint an OIDC token and use it to authenticate to the cloud / PyPI itself. zizmor flagged this as excessive-permissions with high confidence.id-token: write to the publish job only:permissions: { contents: read } # workflow default
jobs:
build:
permissions: { contents: read }
...
publish:
permissions: { id-token: write, contents: read }
...truestep-security/harden-runner egress filtering
.github/workflows/publish.yml — both jobspython -m build can exfil to any destination — there is no eBPF egress monitor / blocker on the runner. Harden-Runner would have detected the tj-actions, axios, and Shai-Hulud incidents at exfil time.- uses: step-security/harden-runner@<sha> # v2.17.0
with:
egress-policy: audit
disable-sudo: trueRun in audit mode for a week to discover legitimate endpoints, then flip to block with an explicit allowed-endpoints: list (PyPI mirrors, GitHub API only).true — audit mode is safe to add unconditionallyactions/checkout missing persist-credentials: false
.github/workflows/publish.yml:15persist-credentials: false, the GITHUB_TOKEN remains in .git/config. Any later step that uploads the workspace as an artifact (or invokes a third-party action that does so) leaks the token. zizmor labels this artipacked. In this specific workflow only dist/ is uploaded, so direct leak risk is low — but the pattern should be eliminated regardless.- uses: actions/checkout@<sha> # v4.2.2
with:
persist-credentials: falsetrue.github/workflows/publish.yml — no cyclonedx / syft / spdx step- name: Generate SBOM
run: |
uv tool install cyclonedx-bom
cyclonedx-py environment -o sbom.cdx.json
- uses: actions/upload-artifact@<sha>
with: { name: sbom, path: sbom.cdx.json }Attach to the GitHub Release alongside wheels.true.github/dependabot.yml — missing# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule: { interval: "weekly" }
cooldown: { default-days: 7, semver-patch-days: 3 }
- package-ecosystem: "github-actions"
directory: "/"
schedule: { interval: "weekly" }
cooldown: { default-days: 7 }true.pre-commit-config.yaml for secret detection
pre-commit is already installed in uv tool list — only the config is missing.# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks: [{ id: gitleaks }]
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks: [{ id: detect-secrets, args: ['--baseline', '.secrets.baseline'] }]
- repo: https://github.com/rhysd/actionlint
rev: v1.7.7
hooks: [{ id: actionlint }]
- repo: https://github.com/zizmorcore/zizmor-pre-commit
rev: v1.25.2
hooks: [{ id: zizmor }]Then: pre-commit install + detect-secrets scan > .secrets.baseline.truepip-audit, osv-scanner, zizmor on PRs
.github/workflows/ — only publish.yml exists, triggered on release; no PR/push workflowmaster without any automated scanner objecting. The only enforcement happens at release time, which is too late if a security regression made it past code review..github/workflows/lockdown.yml via /lockdown baseline — runs on every PR + nightly cron and fails on CRITICAL findings.true — /lockdown baselineosv-scanner, gitleaks, socket, scorecard, trivybrew install osv-scanner gitleaks trivy
curl -fsSL https://socket.dev/install.sh | sh
go install github.com/ossf/scorecard/v5@latestfalse — user installs locallyRun /lockdown fix to apply the auto-fixable items below interactively. Each becomes its own commit.
/lockdown fix)pypa/gh-action-pypi-publish to SHAactions/* uses to SHAsid-token: write to publish job onlystep-security/harden-runner (audit mode) to both jobspersist-credentials: false to actions/checkout.github/dependabot.yml with 7-day cooldown.pre-commit-config.yaml (gitleaks, detect-secrets, actionlint, zizmor)/lockdown baseline.github/workflows/lockdown.yml (CI scanner workflow)osv-scanner, gitleaks, socket, scorecard, trivyEstimated post-fix score: ~92 (Hardened) — assumes all auto-fixable items applied and baseline workflow added.
gh admin scope or human eyes)master: require signed commits, PR with 1 reviewer, dismiss stale, required status checks (add the new lockdown workflow once it's running), block force-push, linear history.pypi environment with required reviewers. Move the OIDC trust scope onto the environment, not the repo.| Safeguard | § | Supply-chain control | Status here |
|---|---|---|---|
| Unique user ID | 164.312(a)(1) | Per-maintainer PyPI accounts; FIDO2 2FA | manual verify |
| Encryption at rest | 164.312(a)(2)(iv) | Secret-scanning, .gitignore coverage | covered |
| Audit Controls | 164.312(b) | Sigstore Rekor transparency log via cosign / SLSA provenance | no SLSA / cosign yet |
| Integrity Controls | 164.312(c)(1) | Lockfile hash pinning, cosign signature verify at deploy, SBOM attestation | lockfile ok; no SBOM/cosign |
| Authentication | 164.312(d) | Trusted Publishers OIDC (no long-lived tokens), MFA | Trusted Publishers active |
| Transmission Security | 164.312(e)(1) | TLS-only registries, signed manifests | PyPI TLS-only |
| Risk Analysis | 164.308(a)(1)(ii)(A) | Continuous CVE scanning in CI, quarterly Scorecard run | no in-CI scanners yet |
| Workforce termination | 164.308(a)(3)(ii)(C) | Off-boarding checklist (GitHub/npm/PyPI/cloud revocation) | runbook needed |
| Activity review | 164.308(a)(1)(ii)(D) | Harden-Runner anomaly alerts to SIEM, monitor cosign verification failures | no harden-runner yet |
| Incident procedures | 164.308(a)(6) | IR runbook for malicious-dep + credential compromise | runbook needed |
| Contingency plan | 164.308(a)(7) | Internal mirror / vendored deps; SBOM for blast-radius queries | no SBOM, no mirror |
| Periodic evaluation | 164.308(a)(8) | Annual third-party pen-test + SLSA self-attestation | internal only today |
4 of 12 HIPAA-relevant safeguards have full supply-chain coverage in this repo; 4 are partial; 4 are missing. Applying the auto-fix plan above moves Risk Analysis, Activity review, and Integrity Controls to "covered" — a 7/12 baseline. The remaining gaps require organizational process (runbooks, off-boarding, external audit), not code changes.
Generated by /lockdown · 2026-05-20 · re-run with /lockdown audit