Pass custom CA in built-in fetchers #654

Open
opened 2025-02-02 21:34:22 +00:00 by raito · 1 comment
Owner

Currently, working with custom CA endpoints that are not part of your system certificate bundle is quite frustrating and has no real easy workarounds to the best of my knowledge.

If you are able to leak environment variables, you can try to influence their behaviors via SSL_CERT_FILE or NIX_SSL_CERT_FILE but it's not guaranteed to affect the daemon's environment except… if you just cause that.

Describe the solution you'd like

Any TLS/network related built-in should accept CApath or CAfile in the sense of OpenSSL or curl, that is: either a file or a path to a set of bundles.

And propagate this adequately to the underlying fetchers.

Enabling:

builtins.fetchGit {
     url = "custom.ca.com";
     cafile = ./pki/root.pem;
 }

Describe alternatives you've considered

  • Send the information about SSL_CERT_FILE to the daemon and let it reexport the variable to its children
  • Wait for IPC protocol and make fetchers just a simple derivation (ongoing action plan by horrors on this)

Additional context

I can send a CL if we agree on the design of the feature.

## Is your feature request related to a problem? Please describe. Currently, working with custom CA endpoints that are not part of your system certificate bundle is quite frustrating and has no real easy workarounds to the best of my knowledge. If you are able to leak environment variables, you can try to influence their behaviors via `SSL_CERT_FILE` or `NIX_SSL_CERT_FILE` but it's not guaranteed to affect the daemon's environment except… if you just cause that. ## Describe the solution you'd like Any TLS/network related built-in should accept `CApath` or `CAfile` in the sense of OpenSSL or curl, that is: either a file or a path to a set of bundles. And propagate this adequately to the underlying fetchers. Enabling: ```nix builtins.fetchGit { url = "custom.ca.com"; cafile = ./pki/root.pem; } ``` ## Describe alternatives you've considered - Send the information about `SSL_CERT_FILE` to the daemon and let it reexport the variable to its children - Wait for IPC protocol and make fetchers just a simple derivation (ongoing action plan by horrors on this) ## Additional context I can send a CL if we agree on the design of the feature.
Owner

Hmmm, except built in fetchers in the language are actually client side. The only fetching that's on the daemon is builtin:fetchurl or FODs. So it's a matter of giving the client the correct certs, today, and there should be very few security implications to the whole thing. Note there's been a security bug due to former lack of cert checking in builtin:fetchurl; I'm unsure if this is super meaningful to this feature idea though.

On macOS we actually gave up on enterprise certs at work because of nixpkgs curl not consulting the keychain for certs. On discussing with a friend at Apple we learned that the LibreSSL they use for /usr/bin/curl has some really bad patches that should not be repeated upstream since they use private frameworks, aren't public (except for openssl 0.98), and most crucially can't check the cert usage restrictions correctly, instead trusting the CA for signing all kinds of certs. The correct implementation is that curl itself should call Security.framework for getting system keychain CAs.

The same problem with usage restrictions exists for the directory based trust store; both macOS and Windows and the browsers are way ahead on this.

Anyway, all of this is to say, this infrastructure in curl itself sucks and it should be made better.

Allowing the client to send certs to the daemon can be dangerous in the presence of caching keyed on the URL due to poisoning attacks; I'm not sure if this is the case anywhere in the system today but it's a somewhat concerning type of possible issue.

Hmmm, except built in fetchers in the language are actually client side. The only fetching that's on the daemon is `builtin:fetchurl` or FODs. So it's a matter of giving the client the correct certs, today, and there should be very few security implications to the whole thing. Note there's been a security bug due to former lack of cert checking in `builtin:fetchurl`; I'm unsure if this is super meaningful to this feature idea though. On macOS we actually gave up on enterprise certs at work because of nixpkgs curl not consulting the keychain for certs. On discussing with a friend at Apple we learned that the LibreSSL they use for /usr/bin/curl has some really bad patches that should not be repeated upstream since they use private frameworks, aren't public (except for openssl 0.98), and most crucially can't check the cert usage restrictions correctly, instead trusting the CA for signing all kinds of certs. The correct implementation is that curl itself should call Security.framework for getting system keychain CAs. The same problem with usage restrictions exists for the directory based trust store; both macOS and Windows and the browsers are way ahead on this. Anyway, all of this is to say, this infrastructure in curl itself sucks and it should be made better. Allowing the client to send certs to the daemon can be dangerous in the presence of caching keyed on the URL due to poisoning attacks; I'm not sure if this is the case anywhere in the system today but it's a somewhat concerning type of possible issue.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lix-project/lix#654
No description provided.