kazu-yamamoto / crypton-certificate

Certificate and Key Reader/Writer in haskell
0 stars 5 forks source link

MacOS: obscure failure when program named "security" is not found in the PATH #9

Open bfrk opened 3 months ago

bfrk commented 3 months ago

We got this error message:

<program name>: security: createProcess: posix_spawnp: does not exist (No such file or directory)

It took us a while to figure out where this is coming from. We invoke our program with an empty PATH in order to test a certain behavior. the program uses http-client which creates a connection manager behind the scenes (involving some unsafePerformIO magic) which ultimately calls System.X509.MacOS.getSystemCertificateStore. (A similar problem would occur if we directly called getSystemCertificateStore with none of this magic happening, though perhaps then we could work around it by temporarily changing the PATH.)

There are several possibilities to mitigate this. One would be to run the 'security' command with a full path i.e. "/usr/bin/security" or wherever it is located. But that is also not ideal because what if it is not installed there but in a different place?

This is certainly a corner case most people won't ever run into, so another possibility would be to add an environment variable to specify the path, something like X509_SYSTEM_SECURITY_PATH_PREFIX which a user could set to "/usr/bin/" to override the default ("").

Yet another solution could be to fall back to using a set of hard-coded paths to search for system certificates in case running 'security' fails. Apparently this is how it is done for Linux, so not unprecedented. Possible candidates are listed here: https://apple.stackexchange.com/questions/226375/where-are-the-root-cas-stored-on-os-x

bfrk commented 3 months ago

After discussing this with a colleague, I came back to my original opinion that this is a potential security problem. A procedure named getSystemCertificateStore should under all conditions do what it claims to do (or fail if it cannot). The user of the library expects to get the set of certificates that their system deems trustworthy, and relying on the PATH to find the 'security' tool violates that contract. So the library should either use a fixed absolute path like /usr/bin/security or set the PATH to some trusted set during the invocation.