Until signing is standardized, it is hard to imagine using nix in any production use case that protects anything of value.
Until signing is standardized, it is hard to imagine using nix in any production use case that protects anything of value.
You don't need to trust it wasn't packaged maliciously, nix does reproducible builds so you can just look at the derivation and build it yourself if you don't feel like relying on the binary cache.
As for whether the underlying contents are malicious, that's between you and the developer. If other distributions have have lead you to believe otherwise, then I think they have misled you.
The only exception I can think of is Tails, and they don't exactly have the breadth that Nix does.
And yet most of the packages from most major linux distributions are signed. If you are going to spend hours maintaining a package, it takes only an extra half a second to tap a yubikey to prevent someone from impersonating you.
Package maintainers from say Arch and Debian go through a vetting process, multiple people sign their keys, and it is a responsibility. Yes, it is volunteer, but there are also volunteer firefighers. Some volunteer jobs are important to keep others safe, and they should be done with care.
If Arch, Debian, Fedora, Ubuntu can all sign packages, then this excuse does not really hold for Nix.
"You don't need to trust it wasn't packaged maliciously, nix does reproducible builds so you can just look at the derivation and build it yourself if you don't feel like relying on the binary cache."
Reproducible builds and package definition signing solve totally different problems. Assume you trust a given developer has been maintaining a package non-maliciously, then you see they made a new update, and so you and other people trust it and build it. You get the same result, so you trust the binaries too. However, you still end up with malware. How? Simple. The developers github account was compromised due to a sim swap on their email account while they were on vacation, and someone pushed a fake commit as that person.
Or maybe a malicious Github employee is bribed to serve manipulated git history only to the reproducible build servers but to no one else, so it goes undetected for years.
Supply chain attacks like this are becoming very common, and there is a lot of motivation to do it to Linux distributions which power systems worth billions of dollars regularly.
It is also so easy to close these risks. Just tap the damn yubikey or nitrokey when it blinks. It is wildly irresponsible not to mandate this, and we should question the motivations of anyone not willing to do something so basic to protect users.
Individual maintainers just commit Nix code to build the packages... Do you mean you want their Git commits to be signed?
Edit: I guess that is what you mean. That is distinct from package (binary) signing. How do you know that a distro's repos built using the signed commits? NixOS is actually better suited to prove that an particular commit produced the package.
Also packages being built by a central party is actually a problem. What stops someone with ssh access to the build systems from tampering with the results?
An input addressed derivation’s hash is based on the the hash of all its input derivations and its own derivation. Therefore trusting the association between the cached binary and the derivation requires trusting the builder and a signature. All non-derivation inputs like source code, must be content-addressed.
A content addressed derivation can then be produced easily by rewriting all the derivations with `nix make-content-addressed`. This doesn’t require trust / signatures as every stage of the build is now content-addressed. The final hash could be confirmed through social consensus of multiple distrusting parties.
There’s nothing in theory stopping you from starting with a content addressed derivation other than it being a pain in the ass as you’d have to know the output hash before you built it, or TOFU (trust on first use) it which is then just the same as using the `nix make-content-addressed` approach.
I’m not sure why you think commit signatures are required. Git is content addressed, you can’t tamper with the derivations without changing the hashes and nixpkgs is primarily developed through GitHub. If someone has access to your SSH keys or GitHub account password it stands to reason they’d have access to your GPG keys too.
9/10 popular package developers I audit have SMS as a backup account recovery method on their email accounts. Easy to see when I try to reset their email passwords and it says "sms sent to ....". One sim swap and I have the account of a popular package maintainer.
Or, even easier, developers often use custom email domains. Right now there are -thousands- of custom email domains used by package maintainers in NPM for instance, that are expired. Buy domain, and you buy access to contribute commits to an unpopular unnoticed package that a popular package depends on.
Supply chain attacks are my core area of research, and they are easy to do. They are hard to defend against unless you have reproducible builds already. It is crazy NixOS has done so much good work for supply chain integrity and refuses to do the first mile almost every other popular linux distro already makes at least some attempt at.
As for PGP key theft, most people that use PGP today keep the keys on personal HSMs, like a yubikey or nitrokey, such that the private key never comes in contact with the memory of an internet connected computer. Stealing one in most cases would require keylogging the pin, and physically stealing the key.
If you got malware on someones machine, you could still manipulate them at that point in time, though this still will require timing your attack so that they are online and tricking them to tap their key, which dramatically increases attack complexity.
Next level once people sign commits though, is signing code reviews. Then you have removed all single points of failure from your software supply chain.
You're free to map your package definitions to the commits they contain and verify any signatures that you find there, but that process will have nothing to do with whether other people have signed the instructions that your machine follows to fetch and build the contents of that commit.
Compare to the Arch model where all official packages must be signed with keys belonging to a reasonably well vetted web of trust.
Developers outside the web of trust that want to contribute yolo unsigned packages to Arch still can, but those must go into AUR where users must opt-in to and manually review each individual untrusted/unsigned package.
https://wiki.archlinux.org/title/Pacman/Package_signing
Nix decided to have the yolo AUR model by default, with no method to elect to use only signed packages, because signing and web of trust are not even supported at all, even optionally.
This is wildly irresponsible given how many people use Nix today.
Nix is two steps forward in deterministic, immutable, and unprivileged package management, and one giant leap backwards in supply chain integrity.
This is why we cannot have nice things.
One magical thing about Nix is that there's a very small divide between managing to install software in the first place and creating an artifact that others can use for the same purpose.
Because of this, practically every NixOS user has their configuration in source control--we're basically each building our own Linux distro with only packages that we trust. Some of us probably sign those commits too.
The ecosystem is useful because it encourages this kind if participation. Having a list of privileged maintainers would interrupt this.
It's unsurprising that a group of people who has worked quite hard to make this possible would be uninterested in creating a scheme whereby they are now responsible for determining which of their users creations is legitimate. Nix attracts users who are interested in that sort of thing, so let it be a userspace problem.
If you want to curate a list of trustworthy packages and work with their developers to set up a chain of trust that starts in a yubikey extends to a signature in a flake output, then I'll help because that sounds like useful work, but I wish you would stop criticizing a brick for not already being a house.
I suppose where my, perhaps misdirected, anxiety comes from is that I run a security consulting company and see NixOS being used as-is in high risk applications, to compile binaries responsible for protecting peoples property or safety, and on the workstations of production engineering teams. Places where it has no business being because supply chain integrity is a non goal.
Maybe you are right though, and the answer is not trying to add supply chain security practices onto a community that does not want them, but to create a security focused fork of that distro that can inherit all that great community work and be a drop-in replacement for NixOS in environments where supply chain security is of critical importance.
I tried and failed to get buy-in for even -optional- expression integrity support back in 2018 and gave up on nix after that. https://github.com/NixOS/rfcs/pull/34
I did prototype a git multisig solution in the years following that though: https://git.distrust.co/public/supsig https://git.distrust.co/public/git-sig
It is already being used in production by some as nothing better exists atm.
A security focused Nix fork that imports, reviews, and git-sig (or similar) signs commits from NixOS and has signature verification built into the package manager, is probably the only way forward, and I would be willing to ally with others interested in this.
- getting a dev sig when they get the code
- checking that sig
- adding a packager sig
And then you need to somehow inject a check before the user comes in contact with the outputs:
> are these signers in my trusted list?
Your users can then enable dev-sig-mode and point their sig checker at the list of keys. Hopefully that's less than whatever a fork of the whole OS entails.
Rather than framing it as a move towards signatures for all of NixOS, I'd frame it as you have a community of users who are willing to maintain a list of trusted keys and work with developers to standardize signature hand-off, and you want to add experimeny features to serve the little pocket of Nixdom that you're carving out for those users.
Avoid anything that smells like you're expecting NixOS act as an authority over which packages are trustworthy and for its devs do the political work of maintaining that list on behalf of the users. Many of us have landed at NixOS because we want less of that top-down nanny business, but we probably like the idea that users would themselves configure such a list.
I can maybe help come up with a standard flow for the signature hand-off, but the harder thing will be intercepting the myriad ways that a user might come in contact with derivation outputs and putting a sig check in their path. You may need another ally that knows the guts better than I do, not just the packaging side of things.
Hopefully we don't have to tamper with nix-env and nix-shell and `nix flake build` and `nix flake run` and `nix flake develop` all separately. Hopefully there's some common place where inbound bits can be checked regardless of how the user has asked for them.
I was informed the way to get changes into Nix was go ask the Nix Gods in the form of an RFC. I did that, and there was some interest, but ultimately it descended into bike shedding about optimal signing schemes and the idea was ultimately rejected by said Nix Gods. I felt very nannied to be honest, and felt I had to give up on nix.
I have had no viable alternatives but to use Arch and Debian for high security build systems across the industries I service and write all sorts of kludgy tools to hash pin packages to get deterministic results since that is what I can prove the integrity of back to the authors.
If you feel you have the social capital with nix leadership to try another RFC for an optional signature verifier hooked into nix user tools for both nix core and expressions, with optional signing from either authors or community members, that would be welcome progress and would certainly make me give the path of directly working with the nix community (vs forking) a second look.
My ideal would be to point nix at a repo of public keys, and nix would not download or execute anything whose supply chain did not start with those keys. This would be incredible for say docker build containers that only need small subsets of packages like compilers for a start... and then eventually a full bootable set of packages supported.
I would happily review any such proposals are capable of meeting threat models requiring high supply chain security.
Contact info on https://lance.dev
Because now that we have reframed it as something that puts users in explicit control of their trust graph and not something that would make NixOS like all the other distros, it's a feature that I'd like to use.
----
I'm working on a data annotation layer which I intend to apply as a filesystem and use nix and my test case. Edits are conceived of as annotations, so there's this sense that every file can be built by following a path of edits from the empty file. This makes for slow reads, but near-instant copies (you're just adding a new pointer at the same position in the edit graph as the file you're copying). It's a strange design choice, but it would solve some problems when using nix flakes with large repositories (everything gets copied into the nix store and it can take a while).
Signatures are exactly the sort of thing I was imagining living in an annotation. Ideally, the annotation adheres to patterns in the data and not the named file, so if the package applied a patch which invalidates the signature then the signature doubles as a link to the original, which can be diffed with the patched version and the user can be shown why it fails, not just that it fails. It's a long shot but that's the dream.
With a bit of luck I'll find a more elegant way to handle this without playing whack-a-mole with each user facing utility that builds a derivation. Maybe some kind of dashboard which shows you which files the system is rendering and whether they have associated signatures (or other metadata, known malicious, etc). The challenge, in the signature case, will be knowing which files are ok to be unsigned and which need to fail on read if not signed. Certainly we can't require a separate signature for every file we render.
It might be a long time coming though, this work proceeds on weekends and holidays and it's pretty far from a useful state. I'm still fiddling with tuning the rolling hash based fragmentation algorithm such that files are constructed out of right-sized fragments which end up being reused if the files are similar.
...which is why it's irresponsible to sign packages unless you have a strong enough relationship with the developer (or are that developer) such that you would notice the malicious release. Signing packages without that level of trust creates a false sense of security in the user.
The Nix approach is to solve the packaging problems in a transparent and verifiable way so that the users can more quickly move from scrutinizing the package to scrutinizing the underlying software--which is where the scrutiny is most helpful anyway.
> we should question the motivations of anyone not willing to do something so basic to protect users.
There are a lot of valid criticisms you could reach for about Nix or its community, but lazy about security just isn't one of them. Our strategy involves different trade-offs than is typical, but that doesn't make them negligent or malicious.
I agree most of the value of signing happens if we establish a web of trust with signed keys of known developers with a history of behaving non maliciously -and- also have signed code review by people in the same trust network to limit risk of coercion, or malware stealing yubikey taps on an endpoint.
Also, saying they are lazy about security is unfair. They just invested in areas of security most distros ignored, but sadly at the expense of the security most distros get right. The regression feels irresponsible, but as I said in my other post maybe we need to separate concerns between the AUR-style rapid development expression repohsitory and a new separate one select packages graduate to that have web of trust with well known maintainer/reviewer keys.
I could get behind that.
The NixOS build system signs all build outputs with its key and the signature is verified upon download. If you’re paranoid, Nix at least makes it easy to just build everything from source.
As for Debian, maintainers must still all be part of the web of trust with an application process and a registered key in the web of trust to contribute packages. https://wiki.debian.org/DebianMaintainer#step_5_:_Keyring_up...
Arch also still has each maintainer sign the packages they maintain, and there is a similar approval process to earn enough trust in your keys to become a maintainer, so there is a decentralized web of trust. Then you add reproducible builds on top of that to almost complete the story.
Signed reviews would remove the remaining SPOFs in debian and arch but sadly no one does this. Nix however does not even allow -optional- key pinning or verify signatures of any authors that choose to sign expressions or their commits, so NixOS is way behind Arch and Debian in this respect.