New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
set tls.rejectUnauthorized option as true by default (#25) #27
set tls.rejectUnauthorized option as true by default (#25) #27
Conversation
19757bd
to
a546b99
Compare
will be reset to "false" if "NODE_TLS_REJECT_UNAUTHORIZED=0" environment variable is present
a546b99
to
ebea6b8
Compare
Setting this setting to Are you also configuring |
Hi
For now, I've tested with a valid but expired certificate on the backend side (and so without any
|
Hi again. I've run different scenarios
The code is like following: const https = require('https');
const fs = require('fs');
const globalAgent = require('global-agent');
globalAgent.bootstrap();
/**
* call 'example.org' to test requests to a public endpoint with a well-known public certificate
* then retry with a custom 'my.private.host' hostname to test requests to a private endpoint with a self-signed certificate.
const hostname = '.....';
*/
const options = {
hostname,
port: 443,
path: '/',
method: 'GET',
};
/**
* 3 steps to be tested:
* - without giving the 'ca' parameter (ie. leave following line commented)
* - with default Certificates Authority from OS (ie. in Ubuntu: /etc/ssl/certs/ca-certificates.crt )
* - with the self-signed certificate used for my.private.host
options.ca = fs.readFileSync('/path/to/ca/cert');
*/
// Call the endpoint and log response headers or error:
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
});
req.on('error', (e) => {
console.error(e);
});
req.end(); Here are the results, with actual version of global-agent, and with my fix: hostname = 'example.org'(public hostname signed with valid known certificate)
hostname = 'my.private.host'(private hostname signed with /my/custom/certificate.crt)
tested with node 12 in Ubuntu 20.04 |
Note: thinking again about the issue, I see another problem with actual code : const options = {
hostname,
port: 443,
path: '/',
method: 'GET',
rejectUnauthorized: true
}; the request shoud be rejected if the server's certificate is invalid. That is the behaviour while sending the request directly without using the global-agent proxy. We should rather delete lines 156-163 and replace line 149, like that: (NB: note that according to NodeJS official documentation, the only value of the env var that disables the certificate validation is |
+1000. As it is this appears to be a critical security vulnerability for everybody using this package right now. This completely disables TLS for connections beyond the proxy, so anybody (the proxy or anybody beyond the proxy on their network route) could impersonate any server at all. With this defaulting to Note that Node.js itself strongly discourages ever setting NODE_TLS_REJECT_UNAUTHORIZED to
As context, there's two cases here I think: For the common case of visiting a normal HTTPS site via a non-intercepting proxy (which takes a CONNECT and creates a direct tunnel upstream), this isn't required. The TLS connection will be made directly with the remote server, which will have a normal trusted CA certificate like any other site, and we should verify the connection to that server like any other HTTPS connection (so we don't need to disable The case where you might need to change how verification works is for an HTTPS-intercepting proxy. This does happen in some enterprise environments, where the proxy uses a trusted company CA certificate to decrypt, examine, and then proxy all data upstream (to scan for leaking company secrets, scan responses for viruses, this kind of thing). Even in that case though, nobody should use In short: nobody should be using I'd suggest adding a test too, to ensure that bad certificates are rejected when using default settings (badssl.com is widely used for testing this). I've just tested manually, and it seems that this issue still affects the new v3 release. Unless I'm missing something (possible?) this is a very serious vulnerability, and probably needs a formal CVE vulnerability report to be published too, to ensure everybody using this module is notified and updates immediately. Anybody using the affected versions today with the default settings is vulnerable to trivial attacks against all of their HTTPS traffic. |
(I've sent an email to @gajus to discuss some of the sensitive details of this and work out a good solution) |
This is now resolved separately by #48, in addition to another issue, so I think this can be closed. |
cf. comment here: #25 (comment)
the option will be reset to "false" if "NODE_TLS_REJECT_UNAUTHORIZED=0" environment variable is present (here: https://github.com/gajus/global-agent/blob/master/src/classes/Agent.js#L161 )
But we need to be sure it will be set to "true" otherwise.