# Rebuild a compromised package (internal supply chain)

Source: https://www.testifysec.com/docs/cilock/use-cases/litellm-supply-chain

LiteLLM was backdoored on PyPI. A Claude Code session stands up an internal supply chain with CI/lock — build the wheel from a forked source under eBPF, scan it, verify the chain against a signed policy, install it with zero egress, and use it — then reports.

In March 2026 `litellm==1.82.7` and `1.82.8` shipped to PyPI with a credential stealer hidden in a `.pth` file that executed on every Python interpreter start. No `import litellm` required. The structural fix isn't "pin harder" — it's **stop trusting the public artifact**: fork the source you've reviewed, build it yourself, and prove every step.

 

This session is a real, unedited [Claude Code](https://claude.com/claude-code) run. The developer asks Claude to stand up that internal supply chain; Claude drives the real `cilock` CLI and the Linux kernel does the rest.

 

A Claude Code session building LiteLLM from a forked source with CI/lock under eBPF tracing, verifying it against a signed policy, installing it, and using it

[Download terminal recording (.cast)](https://www.testifysec.com/media/docs/recordings/hero-demo.cast)

 

## What it does, step by step

 

The recording is the script — here's what each step proves.

 

1. **Snapshot the source.** `cilock run --step source --capture-mode walk` records a signed [`material`](https://www.testifysec.com/docs/cilock/attestors/material) tree (Merkle root) of the forked LiteLLM source. That digest is now the trusted source of record.
 2. **Build under tracing.** `cilock run --step build --trace -- uv build --wheel` wraps the wheel build. [`--trace`](https://www.testifysec.com/docs/cilock/concepts/capture-modes) captures kernel-side — **eBPF in this recording, with automatic ptrace+seccomp fallback where eBPF can't load** — recording what the build *read* (≈2,778 source materials in) and *wrote* (the wheel out): SLSA-style [build provenance](https://www.testifysec.com/docs/cilock/attestors/slsa) linking inputs to the output, signed.
 3. **Scan the source.** `cilock run --step scan --trace -- trivy fs …` wraps a [Trivy](https://www.testifysec.com/docs/cilock/tools/trivy) vulnerability scan, also under eBPF.
 4. **Read the policy.** The signed Witness policy is shown on screen — its `approved-internal-fork` Rego rule requires the build's git remote to be the approved fork, never PyPI.
 5. **Verify the chain.** `cilock verify` checks the `source`, `build`, and `scan` attestations against the policy, anchored on the wheel's product-tree digest → **Verification succeeded**. See [policy verification](https://www.testifysec.com/docs/cilock/concepts/policy-verification).
 6. **Install under eBPF.** `cilock run --step install --trace -- pip install …` captures exactly what installation touches — and confirms **zero `.pth` files** were written and **zero network egress** occurred (the opposite of the compromised artifact).
 7. **Show the egress.** A kernel-level network summary: the build and install made **zero outbound connections**, while CI/lock even caught Trivy itself doing DNS + a TLS connect during the scan — you see your own tools' egress, not just your code's.
 8. **Use it.** The verified wheel is installed into the team's service and called — running from the internal supply chain, never PyPI.

 

Every artifact is a signed DSSE + in-toto envelope; nothing in the recording is faked.

 

## Swap in the tools you use

 

The scan and build steps wrap *any* command, so the same shape works with the scanner and packager your team already runs:

 

- **Vulnerability scanning:** [Trivy](https://www.testifysec.com/docs/cilock/tools/trivy) (shown), [Grype](https://www.testifysec.com/docs/cilock/tools/grype), [osv-scanner](https://www.testifysec.com/docs/cilock/tools/osv-scanner), [govulncheck](https://www.testifysec.com/docs/cilock/tools/govulncheck).
 - **SBOM:** [Syft](https://www.testifysec.com/docs/cilock/tools/syft) emits an [SBOM attestation](https://www.testifysec.com/docs/cilock/attestors/sbom) for the same build.
 - **Static analysis:** [Semgrep](https://www.testifysec.com/docs/cilock/tools/semgrep), [gosec](https://www.testifysec.com/docs/cilock/tools/gosec), [CodeQL](https://www.testifysec.com/docs/cilock/tools/codeql) as additional signed steps.
 - **Secrets:** add the [`secretscan`](https://www.testifysec.com/docs/cilock/attestors/secretscan) attestor to fail the build on a leaked credential (see the [CI credential-harvester use case](https://www.testifysec.com/docs/cilock/use-cases/credential-harvester)).

 

## Why it matters

 

A pin protects you from a *different* artifact; it does nothing when the artifact you pinned to is itself malicious. Building from reviewed source under kernel-level tracing, then gating on a [signed policy](https://www.testifysec.com/docs/cilock/concepts/policy-verification), turns "trust PyPI" into "verify our own evidence." The same evidence model carries through scan, install, and runtime — [one spine](https://www.testifysec.com/docs/cilock/concepts/the-spine-of-the-graph), many checkpoints.

Reference generated from the product documentation. Match commands and support details to your installed release.
