# Python Supply Chain

> Hardens a Python repository's supply chain — Dependabot update automation, pip-audit vulnerability scanning, secret scanning and push protection, CodeQL, OpenSSF Scorecard, SBOMs, CODEOWNERS. Use for 'set up dependabot', 'audit dependencies', 'enable secret scanning', 'harden this repo'. Not for CI quality gates, workflow hardening, or PyPI publishing.

- **Type:** Skill
- **Install:** `agentstack add skill-paldom-python-skills-python-supply-chain`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Paldom](https://agentstack.voostack.com/s/paldom)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Paldom](https://github.com/Paldom)
- **Source:** https://github.com/Paldom/python-skills/tree/main/skills/python-supply-chain

## Install

```sh
agentstack add skill-paldom-python-skills-python-supply-chain
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# python-supply-chain

Installs layered supply-chain controls into a Python package repository on GitHub:
dependency-update automation with a freshness delay, vulnerability and secret
scanning, code scanning, ownership rules for the paths that define automation, and
SBOM/provenance artifacts. The design premise, taken from the 2025–2026 incident wave
(the Shai-Hulud npm worm, the malicious `axios` release spread by dependency bots,
mutable-tag action compromises), is that the attack surface is now *your automation
and the first hours after a release* — so no single control below is sufficient, and
bot output is treated with the same suspicion as human PRs.

## When NOT to use

- **CI quality-gate workflows, branch rulesets, action SHA pinning, zizmor** — the
  python-ci skill, if installed, owns those. This skill only adds *scanning* and
  *update* workflows, and notes where a control depends on a ruleset.
- **PyPI trusted publishing (OIDC) and the tag-triggered publish workflow** — the
  python-release skill. This skill stops at repo-side SBOM/provenance; the publish
  step that uploads to PyPI belongs there.
- **Pre-commit hook wiring** (including a local gitleaks hook) — the
  python-precommit skill. Local hooks are advisory; this skill installs the
  enforcing server/CI layer.
- **Packaging and lockfile setup** (`uv init`, `pyproject.toml`) — python-packaging.
- **Agent hooks / AGENTS.md rules** — agent-guardrails. This skill only *protects*
  agent-config paths via CODEOWNERS.
- **Active incident response** beyond credential rotation basics — escalate to a
  human; do not attempt autonomous cleanup of a live compromise.

## Workflow

Work through the steps in order; each is independently valuable, so stop where the
user's scope ends. Steps that change GitHub settings need `gh` authenticated with
admin rights on the repo — otherwise print the commands for the user to run.

### 1. Audit the current posture

Run the bundled read-only checker from the repo root before adding anything:

```bash
python3 "${CLAUDE_SKILL_DIR}/scripts/check_supply_chain.py" --root .           # file-level checks
python3 "${CLAUDE_SKILL_DIR}/scripts/check_supply_chain.py" --root . --github  # + GitHub-side settings via gh
```

(Invoke it from this skill's folder with an absolute path if cwd differs.) It prints
one `PASS|WARN|FAIL|NOTE check: detail` line per control and exits non-zero on FAIL.
Fix FAILs in the steps below; treat WARNs as the backlog. Never duplicate a control
that already exists — tune it instead.

### 2. Baseline: a committed lockfile

Every control below assumes the dependency set is pinned and committed: `uv.lock`
(preferred), `poetry.lock`/`pdm.lock`, or hash-pinned requirements
(`--generate-hashes` with pip-tools). If there is no lockfile, that is a
python-packaging problem — flag it and stop; auditing an unpinned dependency set
audits a guess.

### 3. Dependency-update automation (Dependabot)

Write `.github/dependabot.yml`:

```yaml
version: 2
updates:
  - package-ecosystem: "uv"        # uv.lock projects; use "pip" for requirements/pip-tools/poetry
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    cooldown:
      default-days: 7              # skip versions published .

### 6. Secret scanning, push protection, and a CI backstop

GitHub-side scanning is free and on by default for public repos; private repos need
GitHub Secret Protection licensing. Enable/verify both toggles:

```bash
gh api -X PATCH "repos/{owner}/{repo}" --input -  before adding anything.

### 10. SBOM and release provenance

Two SBOM paths — pick per audience:

```bash
# Repo-level SPDX from GitHub's dependency graph (compliance requests):
gh api "repos/{owner}/{repo}/dependency-graph/sbom" --jq .sbom > sbom.spdx.json

# Build-time CycloneDX from the lockfile (ship next to the wheel):
uv export --format requirements-txt --no-emit-project -o /tmp/sbom-req.txt
uvx --from cyclonedx-bom==4.4.3 cyclonedx-py requirements /tmp/sbom-req.txt -o sbom.cdx.json
```

For releases, attest the built artifacts with `actions/attest-build-provenance`
(and `actions/attest-sbom` for the SBOM) inside the release workflow — snippet and
required permissions in the reference. The publish workflow itself, and PyPI-side
attestations via trusted publishing, belong to the python-release skill. Tell the
user the honest limit: an attestation proves *where and how* an artifact was built,
not that it is safe — real campaigns have shipped validly-signed malicious builds —
and it only matters if consumers verify (`gh attestation verify dist/pkg.whl
--repo OWNER/REPO`).

### 11. Re-audit and hand off

Re-run step 1; the script should report no FAILs. List remaining WARN/NOTE items
with a one-line reason each (deliberate skip vs. needs licensing vs. sibling-skill
territory).

## Output spec — what done looks like

- `.github/dependabot.yml` with a pip or uv ecosystem entry, weekly schedule,
  cooldown, grouped minor/patch updates, and a github-actions entry.
- Committed lockfile; a documented, pinned pip-audit invocation (or scheduled scan).
- Secret scanning + push protection enabled (or exact commands handed to the user
  when permissions/licensing block it), plus a CI gitleaks backstop.
- CodeQL enabled (default setup or committed workflow).
- CODEOWNERS covering `/.github/` and agent-config paths, with the
  branch-protection dependency stated in the handoff.
- Optional per scope: Scorecard workflow, SBOM artifact, attestation step wired into
  the release workflow (or delegated to python-release).
- `scripts/check_supply_chain.py --root .` exits 0.

## Failure modes and gotchas

- **`uvx pip-audit` without `-r` audits the wrong environment** (the tool's own
  ephemeral venv) and happily reports zero findings.
- **Dependabot cooldown can wedge frequently-released dependencies**: the filter has
  evaluated only the latest release, so a dep that ships weekly may never propose an
  update (dependabot-core #14234/#14579; partially fixed — verify current behavior).
  Symptom: a dependency silently months stale despite Dependabot running green.
- **Cooldown at the package-manager level blocks security fixes**; Dependabot's
  cooldown does not (advisory updates bypass it). Don't replace one with the other.
- **Cooldown is not proven for transitive dependencies** (confirmed gap for npm in
  dependabot-core #14683; unverified for pip/uv) — the lockfile audit in step 4 is
  the control that actually covers transitives.
- **Bot-authored PRs carry unearned trust**: attackers mimic Dependabot branding,
  and auto-merge-on-green shipped malware in the axios incident. Review like any PR.
- **Dependabot does not alert on SHA-pinned actions** (only semver tags) — a known
  gap between this skill's alerting and python-ci's pinning policy; the dependabot
  `github-actions` entry still proposes pin bumps, so keep it.
- **gitleaks-action requires a license key for organization repos**
  (`GITLEAKS_LICENSE` secret; free for personal accounts) — a silent-failure setup
  step people miss.
- **CODEOWNERS is last-match-wins** — a trailing `*` rule overrides every protection
  above it. Put the catch-all first, specific security paths after.
- **Push protection is a subset filter, not a guarantee** — keep the CI backstop.
- **Scorecard is gameable and heuristic** — never wire it as a merge gate; its
  public weekly scan omits several checks (CI-Tests, Contributors,
  Dependency-Update-Tool) for API-cost reasons, so scores differ from local runs.
- **Installing a Python package executes code** — at install time (build backends,
  `setup.py`) and import time. Never install a package to inspect it; read it on
   first. Watch for typosquats (`request` vs `requests`)
  and for hallucinated package names in LLM suggestions (slopsquatting) — verify
  the exact name, repo link, and release history on pypi.org before `uv add`.
- **Free-tier boundary**: dependency graph, Dependabot alerts and security updates
  are free everywhere; secret scanning and CodeQL are free for *public* repos only —
  on private repos, hand the user the licensing decision instead of a broken toggle.

## Files

- [references/dependabot.md](references/dependabot.md) — full annotated
  dependabot.yml, cooldown semantics and bug detail, Renovate comparison,
  noise-tuning, auto-merge policy evidence.
- [references/scanning-and-provenance.md](references/scanning-and-provenance.md) —
  gitleaks/TruffleHog CI workflows, advanced CodeQL workflow, Scorecard workflow,
  SBOM/attestation snippets with permissions, verification commands.
- [scripts/check_supply_chain.py](scripts/check_supply_chain.py) — read-only posture
  audit; `--github` adds GitHub-settings checks via `gh`; exits non-zero on FAIL.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Paldom](https://github.com/Paldom)
- **Source:** [Paldom/python-skills](https://github.com/Paldom/python-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-paldom-python-skills-python-supply-chain
- Seller: https://agentstack.voostack.com/s/paldom
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
