agents/references/threat-model.md
uv is a Rust CLI that resolves, builds, installs, manages, and publishes Python packages; downloads runtimes; and updates itself. It runs with the developer's or CI worker's access to files, networks, repositories, credentials, secrets, and OpenID Connect (OIDC) tokens.
A behavior is a security issue only when an independent attacker controls a concrete input, current uv code or repository automation uses that input to cross a boundary defined below, and the crossing gives the attacker new power or harms a protected asset. Trusted-source compromise, intended behavior, and correctness defects that give an attacker no new power are not security issues.
TLS roots, secure operator-selected mirrors, configured runners, and their intended protocol behavior are trust roots; their compromise or misconfiguration alone is not a uv flaw.
Packages and their sources (indexes, Git repositories, and files) are trusted during initial resolution or explicit lock updates. During a locked operation, the lockfile's sources, object IDs, and hashes are authoritative; uv must not replace them in response to upstream changes.
Attacker-controlled: files and metadata from an untrusted publisher; public package-name registrations; remote Git repositories or refs controlled by an untrusted owner; unauthenticated network responses; archives; malformed protocol data; and changes from an untrusted contributor that a privileged workflow runs before review.
Trusted local input for the product threat model: the entire machine on which uv runs,
including all environment variables; the filesystem and its links; local project files such as
pyproject.toml, uv.toml, requirements, lockfiles, scripts, .python-version, and workspace
members; installed programs and interpreters; virtual environments; PATH; network and proxy
configuration; certificates; credentials; keyring providers; caches; and install directories. CLI
flags, explicit requirements and scripts, maintainer-supplied workflow dispatch inputs, and
choices such as --allow-insecure-host, --no-index, --no-sources, --no-build,
--only-binary, and --require-hashes are also trusted. --no-project, --no-config, and
similar isolation options require uv to ignore relevant inputs.
uv is not normally installed setuid. Running uv as root is not considered a route to local
privilege escalation. Selected packages may run arbitrary code. Interpreter startup, .pth
loading, bytecode compilation, metadata reads, and entry points—including one named
python—change timing, not authority. Execution crosses a security boundary only when it occurs
before uv selects the relevant package, target, or interpreter; violates an effective build or
isolation rule; crosses an actor or privilege boundary; or grants capability beyond what the
selected package already has.
Choosing a trusted local filesystem root authorizes normal operations on its target, including
trusted symlinks and junctions. A path escaping its written directory or following a link is a
security issue only if uv promised to prevent it or remote untrusted data chose the path.
Operations that rely on PATH lookup or explicit relative paths are not security issues because
PATH, CWD, and the filesystem are trusted local input. This includes placing CWD on PATH.
The uv product runs on a trusted machine while processing package, Git, archive, and protocol data from independent suppliers. Its security goal is to preserve the operator's choices about sources, integrity, credentials, execution, and filesystem destinations while handling that data.
--no-build
means binary-only selection but permits backend execution for an explicitly selected editable
source unless a stronger policy applies. Build-backend execution crosses a security boundary only
if it happens before package selection, bypasses the rules that actually apply, escapes build
isolation, or runs with greater privilege..venv, cache, configuration,
symlink, or junction state does not create an escape by itself. Platform-specific rejection and
containment rules define the boundary.astral-sh/versions, its maintainers and GitHub controls, authenticated main, and HTTPS are
trusted. That manifest's checksum is a valid trust root; mutability alone does not require another
uv-embedded digest.The GitHub repository holds uv's source, build and release workflows, and maintainer automation. Maintainers, reviewed changes, protected refs, repository settings, configured runners and environments, and explicitly trusted third-party actions are trusted. Untrusted inputs include public contributions, workflow inputs supplied by untrusted actors, third-party refs or actions outside that trust set, and artifacts passed from untrusted jobs. The protected assets are source history, release artifacts, publishing credentials and OIDC tokens, repository writes, and downstream users.