Node: Node uses an hardcoded list of certificate authorities

Created on 7 Dec 2015  Â·  29Comments  Â·  Source: nodejs/node

I was dumbfounded when I realized that Node uses a statically compiled, manually updated, hardcoded list of certificate authorities, rather than relying on the system's trust store, or even just a directory truststore of its own.

This causes a large amount of problems :

  • Dependancy on the Node community for reactiveness in addition or removal of certificates
  • Dependancy on the Node community in terms of certificate trust
  • Prevents companies and anyone with their own PKI from using their certificates globally
  • Requires support from EVERY node application making use of SSL to include certificates
  • Requires modification of source code if an application doesn't happen to support it
  • Requires modification and rebuilding of Node to remove certificates that wouldn't be trusted by an organisation

Now, I can see no practical use for that. While this is acceptable in a development environment, where you can make changes to your own application, this is outright unusable... and i can't stress enough the security implications for many organisations.

Proposed solutions :

  • Make use of the standard system trust store, like any sensible application
  • Use a dedicated globally installed trust store, allowing user modifications, and why not, handling with npm
  • Dynamically load CAs using relative path, in a way similar to the usage of the node_modules folder

TL;DR: CA Certificates are hardcoded in node. It may be OK for dev, but it sucks big time for ops.

tls

Most helpful comment

I don't get that attitude. You feel strongly enough to complain about it on the bug tracker, apparently strongly enough to switch to a different language but not strongly enough to spend an hour or two on a pull request. The whole point of open source is that you can change it if you don't like what it does.

All 29 comments

Indeed, a distribution like debian needs to work around that using that kind of patch.

I already asked this in
https://github.com/nodejs/node/issues/3159
I suppose a pull request could make it now ? @fir4 feels like writing one ?

@kapouer Path should not be hard-coded. Also what for other distributions of Linux, and other OSs like Windows and OS X ? This issue requires more research

I think the simplest thing to do is to have a configurable path as a build option - so that each distributor can point nodejs to the right place where it can find the system-installed root ca(s).
I don't think it's worth the time spent to be able to change that path at runtime.

Yeah, those were simple ideas, in case you'd want more flexibility. Using a configurable path on ./configure step would be a great start, however I have literally zero idea how Certificates are handled on MacOS and Windows...

For Windows it's too complicated. It's not just a folder. I'm thinking of a solution... Have a download link to an automatically generated zip file with the CAs. Bundle the current version with each distribution of nodejs. Add an environment variable to nodejs to locate the CAs folder. The installer will extract CAs to a proper location and set the environment variable. For Unix-like systems, the installer may try to locate system CAs. If no installer, this will have to be done manually.

EDIT: By default, use a build option like kapouer mentionned.

+1

:+1:

Absolutely +1

Using the systems certificates store would of cause be best.
But even that should be configurable.

A configuration option like the one used by npm (setting a caFile) would be of great help for me and presumably for most others running into problems with ca-certs.

This could be a global configuration option, an environment variable and/or a commandline param.
It should not be a compile option in my opinion - at least not without being overwriteable afterwards.

While this is acceptable in a development environment…

It _may_ be acceptable in _most_ development environments.
Anyhow it is absolutely not acceptable by any means in my development environment nor in some others.

We are working behind a corporate proxy with ssl scanning.
Meaning the secure connection does not exist between our machines and the internet servers but between our machines and a trusted proxy and another between that proxy and the internet servers.

This leads to absolutely unexpected behavior, for example when installing packages using npm.

While we can configure npm to accept our certificate we can not make the postinstall scripts do the same. This leads to many packages not being able to be installed properly.

This means we can not even _npm install_ some simple grunt tasks although npm already has the option to change the trusted CAs.

This is a major issue for commercial deployment of nodejs and a major obstacle to our node based software being adopted by large organizations that have their own in-house PKI. It is also indicative of a problem with the node developers lack of understanding of the importance of doing security "right".

I am very interested in seeing this issue get resolved and if there are sensible ways I can contribute to its resolution, please someone from the NodeJS team let me know (yes, a PR, I realize, but if there is any guidance on how to put that together or other considerations/constraints...)

It is also indicative of a problem with the node developers lack of understanding of the importance of doing security "right".

Please.

yes, a PR, I realize, but if there is any guidance on how to put that together or other considerations/constraints...

Start with reading CONTRIBUTING.md. If you still have questions afterwards, I can probably answer them.

Please.

Please as in, "please fix this" or "please, it is a super good idea to hard code the list of certificate authorities? "

this is outright unusable... and i can't stress enough the security implications for many organisations.

+1.

Please as in, "please fix this" or "please, it is a super good idea to hard code the list of certificate authorities? "

I Think that was a "Please do not assume things".

Please as in, "please fix this" or "please, it is a super good idea to hard code the list of certificate authorities? "

I think its more sort of "please stop being that accusing".

It is also indicative of a problem with the node developers lack of understanding of the importance of doing security "right".

I do not think they do not understand the importance to do it right.
One major problem of security is, that most people do not know, how to do it right and do not see all the problems which may arise. This is btw. a major problem in software engineering in general.

As long as no authoritys certs need to be removed, nobody outside of corporate environments with high security and compliance standards may even notice any problems with the integration as it is today. And nobody outside such environments would even think about all the problems wich will arise inside this environments.

This seems pretty much normal to me and there is no point in being harsh, accusing the developers not to try to do things right or anything alike.

Anyways, in my opinion the issue is of great importance and it needs to be fixed asap.

I Think that was a "Please do not assume things".

Thank you for clarifying.

One major problem of security is, that most people do not know, how to do it right and do not see all the problems which may arise.

I agree. Thanks for taking the time to explain.

We are working behind a corporate proxy with ssl scanning.
Meaning the secure connection does not exist between our machines and the internet servers but between our machines and a trusted proxy and another between that proxy and the internet servers.

This leads to absolutely unexpected behavior, for example when installing packages using npm.

While we can configure npm to accept our certificate we can not make the postinstall scripts do the same. This leads to many packages not being able to be installed properly.

I am in the exact same scenario. This is an important issue that needs a solution.

Putting in my two cents: trying to write a Node application for a major university, and it's not exactly optimal with this issue.

Is anyone currently working on this? Microsoft/tfs-cli#118 has a workaround, but I'd love to see the issue fixed in Node itself.

Is anyone currently working on this?

Not that I know of. I think I speak for the project when I say that we'll review patches but that none of the collaborators feel a strong urge to work on it themselves.

+1

Our product targets education environments, where MITM'ing SSL is almost standard, so this is a major problem for us. We didn't even realise this behaviour was the case until customers kept complaining their certs weren't trusted, since every other piece of software I've seen does this by default.

My workaround is to load and parse the system CA certs manually. Then, as recommended by the request docs, pass them in with the ca option everywhere we make a request. I presume you could also just set ca on the global agent if that works for your use case.

fs.readFileSync('/etc/ssl/certs/ca-certificates.crt')
  .toString()
  .split(/-----END CERTIFICATE-----\n?/)
  // may include an extra empty string at the end
  .filter(function (cert) { return cert !== ''; })
  // effectively split after delimiter by adding it back
  .map(function (cert) { return cert + '-----END CERTIFICATE-----\n'; })

I think I speak for the project when I say that we'll review patches but that none of the collaborators feel a strong urge to work on it themselves.

I guess we should stop using Node to do any serious work then.

Please leave the sarcasm for elsewhere; we'd gladly review a patch for this if someone were to make a pull request.

Most of us are pretty busy so we can't necessarily guarantee when this will get done if no-one steps up, though.

I am sorry, it seems I didn't made clear what my point is. There was absolutely no sarcasm intended in any way.

See: As we can not influence the environments our projects need to run in, we simply can not build upon a foundation which does not cover such cases.

We had to move an entire project to a different language, as it was impossible to make it work using Node inside our clients environment.

I don't get that attitude. You feel strongly enough to complain about it on the bug tracker, apparently strongly enough to switch to a different language but not strongly enough to spend an hour or two on a pull request. The whole point of open source is that you can change it if you don't like what it does.

I have proposed a solution and I think it will be more productive if others do the same or make a pull request instead of just bumping the thread.

Had similar issues with this, have internal apps using an internally signed cert.
Opted to use https.globalAgent and set an array of CA's which are defined in a config and updated on an env basis.

E.g.

const trustedCa = [
    '/etc/pki/tls/certs/ca-bundle.crt',
    '/path/to/custom/cert.crt'
];

https.globalAgent.options.ca = [];
for (const ca of trustedCa) {
    https.globalAgent.options.ca.push(fs.readFileSync(ca));
}

It turns out that https.request module with ca option doesn't support having multiple certificates in pem file. @DuBistKomisch solution solved this problem. I'm using node v4.

@jan-swiecki In https://github.com/nodejs/node/issues/4175#issuecomment-240422257 you mention that

It turns out that https.request module with ca option doesn't support having multiple certificates in pem file

Its not clear if you are talking about a user-land module, but if you are talking about node's https.request() method, I did a some testing, and it supports concatenated PEM certificates in options.ca in node 6.x (which I expected from reading the code), but not node 4.x.

If you can't upgrade, open an issue about it and make the case that this is a feature that should be back-ported to 4 from 6. I'm not sure what the current stance is on back-porting features, but if its low risk, it may be possible.

Setting https.globalAgent.options.ca works for connections to my own server but causes SSL errors for regular connections (which normally work when https.globalAgent.options.ca isn't set). Is there a way to get https.globalAgent.options.ca to append to the default list of certificates used by node?

Not programmatically, but with env configuration it is: https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file

Was this page helpful?
0 / 5 - 0 ratings