Unpacking lockfiles in different package managers

kpcyrd kpcyrd at archlinux.org
Mon Dec 8 17:49:22 UTC 2025


On 12/5/25 2:17 PM, Benoit Baudry wrote:
> Hi everyone,
> 
> We've recently worked on unpacking the various strategies for generating 
> lockfiles in different package manager: "The Design Space of Lockfiles 
> Across Package Managers" https://arxiv.org/pdf/2505.04834
> 
> Shall this ring a bell don't hesitate to reach out

For a broader definition of package manager, I wrote the following two 
tools:

## https://github.com/kpcyrd/repro-env

This is an attempt to apply the concept of Cargo.toml and Cargo.lock to 
GNU operating systems, specifically for build environments - it always 
uses an OCI container image as a base and in the simplest case it's just 
resolving/pinning from `rust:1-alpine3.18` to something like 
`"rust at sha256:...`, but it can also do things like:

```
[container]
image = "docker.io/library/archlinux"

[packages]
system = "archlinux"
dependencies = ["make", "musl", "rust-musl"]
```

and resolve this to a repro-env.lock file, that records all necessary 
(in this case Arch Linux) dependencies including their sha256. The 
packages are downloaded from https://archive.archlinux.org.

I use this tool to build the packages for https://apt.vulns.xyz/, but 
also many of my pre-compiled binaries on Github.

## https://github.com/kpcyrd/updlockfiles

This tool is specifically written to ease my Arch Linux packaging work 
(the name is adjacent to the `updpkgsums` tool).

Generally Arch Linux sticks to the upstream dependency lockfiles (which 
makes it easier to reason about security, patches, etc), but some 
projects refuse to publish resolved dependency trees, and delegate this 
responsibility downstream.

updlockfiles is the tool I use to generate a resolved dependency tree 
from a given source code build input. This step is obviously not 
reproducible because it's a snapshot from a given point in time, this 
snapshot is then committed to our git repositories and considered a 
"normal" source code input[1].

This is necessary because otherwise software from these kinds of 
upstreams can't be reproducible.

In practice it looks like this (see the `updlockfiles()` function, which 
is non-standard to pacman based packaging):

https://gitlab.archlinux.org/archlinux/packaging/packages/psalm/-/blob/0daa55026f8251ef2d478637ff1727a37c92c200/PKGBUILD

The resolved file committed to the git repository looks like this:

https://gitlab.archlinux.org/archlinux/packaging/packages/psalm/-/blob/0daa55026f8251ef2d478637ff1727a37c92c200/composer.lock

cheers,
kpcyrd

PS: I understand that yarn.lock was skipped, but you probably want to 
include composer. :)

[1]: There's a potential discussion for "this isn't source code because 
that would mean I as an auditor would need to review it" - yes you do, 
ideally this file would be upstream so you only need to review it once 
instead of once-for-each-distro, also making triage of security updates 
easier - there's some downstream sharing of those dependency lockfiles 
between Arch Linux and Alpine[2], but it's generally quite chaotic and I 
would rather not do this.
[2]: 
https://gitlab.alpinelinux.org/alpine/aports/-/blob/590fd1489813473277cf110fd88b1c3888d19367/community/wasm-bindgen/APKBUILD#L15


More information about the rb-general mailing list