· 6 min read ·

The Threat Models Behind Astral's Security Practices

Source: hackernews

A package manager that installs packages occupies a specific choke point in software infrastructure. Compromising the installer gives you leverage over every install it performs, which is categorically different from compromising a single library. Astral, the company behind uv and ruff, has become a significant piece of Python infrastructure with unusual speed: uv launched in February 2024 and within months had displaced pip, pip-tools, pyenv, and virtualenv for a large portion of the community. Their recently published security overview describes the controls they have built, and reading those controls against the supply chain incidents of the past two years reveals why each one sits where it does.

The incidents that define the threat model

Two incidents from 2024 and 2025 are worth keeping in mind throughout this.

The first is the ultralytics incident in December 2024. The popular computer vision library had malicious versions uploaded after the maintainer’s PyPI API token was compromised through a GitHub Actions misconfiguration. Those versions were live on PyPI long enough to be downloaded tens of thousands of times. The attack vector was a long-lived credential stored as a repository secret, exposed through CI logs.

The second is the xz utils backdoor, discovered in March 2024. An attacker spent nearly two years building trust as a contributor to the xz project, then injected malicious code into the release tarballs during a build step they controlled. The git repository source code did not contain the backdoor. Auditing the source would not have caught it. Only verifying that the distributed binary matched what a reproducible build from the source repository would produce could have detected it.

These two incidents map onto two distinct attack surfaces: the upload credential, and the artifact itself. Astral’s security model addresses both, and adds controls for two additional surfaces on top of those.

Trusted Publishing: eliminating the stored credential

Astral publishes uv and ruff to PyPI using Trusted Publishing, the OIDC-based mechanism PyPI introduced in 2023. The mechanism replaces stored API tokens with short-lived credentials derived from the OIDC identity of a specific GitHub Actions workflow run. The workflow authenticates to PyPI using the token GitHub issues to the runner, and PyPI verifies that the token corresponds to the repository and workflow file configured on the package’s publisher settings. No credential is stored anywhere in the repository; there is nothing to steal.

The ultralytics attack worked because a token existed. Trusted Publishing removes the token from the equation entirely. The PyPI publisher configuration specifies which repository and which workflow file are allowed to upload, so a compromised CI secret from a different context cannot publish a malicious release. Adoption across the top PyPI packages grew substantially through 2024 and into 2025, driven in large part by incidents showing exactly what the old model cost.

SLSA provenance: closing the artifact gap

Trusted Publishing secures the upload step. It does not verify that what gets uploaded matches the source repository. The xz utils attack was precisely in that gap.

SLSA (Supply-chain Levels for Software Artifacts), an OpenSSF framework, addresses this through build provenance: a cryptographically signed attestation that records the source commit, the build workflow, and the build environment for each released artifact. The slsa-github-generator produces SLSA Level 3 provenance for artifacts built in GitHub Actions, which means the provenance is generated in a hardened, isolated runner environment managed by GitHub rather than by the project. A compromised maintainer cannot forge Level 3 provenance without also compromising GitHub’s infrastructure.

GitHub’s native artifact attestation feature, launched in 2024, brings provenance generation close to zero additional effort in an existing Actions workflow. A user who downloads a uv binary and wants to verify it can run:

gh attestation verify uv-x86_64-unknown-linux-musl.tar.gz \
  --owner astral-sh

This fetches the stored provenance and confirms the artifact came from a specific commit via a specific workflow. An artifact tampered with after the build, in the way the xz utils tarballs were, would not match its provenance and verification would fail. The check is cheap to run and requires no prior setup on the user side beyond having the gh CLI installed.

Sigstore signing and the public record

Release artifacts are also signed using Sigstore, specifically the cosign tool. Sigstore’s model avoids long-lived private keys entirely. The signing identity comes from an OIDC token at signing time; Sigstore’s Fulcio certificate authority issues a short-lived certificate tied to the GitHub Actions runner identity, and the resulting signature is published to Rekor, Sigstore’s append-only transparency log.

The transparency log is the important part. Every signature in Rekor is publicly auditable. A release signed from an unexpected identity, or at an unexpected time, produces a public record that anyone monitoring the log can detect. This is the same principle as certificate transparency in TLS: not preventing abuse outright, but making it observable and attributable after the fact. Combined with SLSA provenance, the two controls together mean that both the origin of an artifact and the act of signing it are independently verifiable from public records that neither Astral nor an attacker can quietly revise.

Pinned Actions: the CI supply chain

GitHub Actions are themselves a supply chain. Third-party actions referenced by mutable version tags (uses: actions/checkout@v4) are a code injection vector: if the tag is moved to a different commit, the CI environment executes different code without any change to the repository that uses it. The tj-actions/changed-files compromise in early 2025 illustrated this at scale: a compromised action dumped CI secrets to build logs across thousands of repositories that referenced it by tag rather than by commit SHA.

Astral pins all third-party Actions to full commit SHAs, so the code that runs in CI is tied to a specific immutable commit. This is one of the checks run by OpenSSF Scorecard, the automated repository security auditing tool. The practice requires ongoing maintenance since pinned SHAs must advance as actions release new versions. Projects typically automate this with Renovate or Dependabot, which open pull requests to update the SHA pins through the normal review process, preserving the security constraint while keeping dependencies current.

The permissions field in workflow files is a related control. By scoping each job to only the GitHub token permissions it actually requires, the blast radius of a compromised step is limited: a job that only needs to read repository contents and write to the attestation store cannot exfiltrate secrets it was never granted access to.

Rust dependency auditing

Both uv and ruff are written in Rust, which eliminates the memory safety vulnerability classes most exploited in C and C++ tools. The supply chain exposure on the code side is the crate ecosystem rather than PyPI. Astral uses cargo-deny to audit Rust dependencies against known vulnerability advisories, enforce license constraints, and detect duplicate crate versions that can mask unexpected transitive dependencies. A configuration that checks the RustSec advisory database looks like this:

[advisories]
db-urls = ["https://github.com/rustsec/advisory-db"]
vulnerability = "deny"
yanked = "deny"
unmaintained = "warn"

Running this in CI means a newly published advisory for any dependency fails the build before a release occurs. Combined with automated dependency updates via Renovate, the feedback loop is short: advisory published, CI fails, automated PR opened with the patched version, review and merge.

How the layers compose

Each control addresses a distinct failure mode. Trusted Publishing removes the stored credential that enabled the ultralytics attack. SLSA provenance provides the artifact verification that was absent in the xz utils case. Sigstore creates a public, auditable signing record. Pinned Actions close the CI supply chain injection vector. Cargo-deny catches known-vulnerable Rust dependencies before they reach a release binary.

SLSA, Sigstore, Trusted Publishing, and pinned Actions are all documented standards with established tooling; Astral did not invent any of them. The blog post is worth reading because a project at this level of infrastructure responsibility has implemented all of them simultaneously, with each layer addressing a gap the others leave open. Removing any single control leaves a realistic attack surface exposed; running them together substantially narrows what an attacker can accomplish without triggering a detectable signal in one of the public logs.

For a tool that runs on millions of developer machines and installs the packages those machines depend on, that combination is the appropriate bar. It is also, given the supply chain incidents of the past two years, a bar that the broader Python ecosystem should be measuring other critical projects against.

Was this interesting?