Deno: Add flag to ignore SSL certificate issues

Created on 18 Dec 2018  路  10Comments  路  Source: denoland/deno

There should be a way to allow insecure https requests, using window.fetch() for example.
It should disable certificate validation for all requests made from the program.

As of implementation, there are two optoins that come to my mind: environment variable and flag. Below are some examples of how it's done in other web-related software, so we can come up with intuitive name and approach.

Examples:

  • In NodeJS, there is a NODE_TLS_REJECT_UNAUTHORIZED environment variable that can be set to 0 to disable TLS certificate validation. It takes name from tls.connect options.rejectUnauthorized
  • In curl, there's a -k or --insecure flag, which allows insecure server connections when using SSL
  • In Chrome, there's a --unsafely-treat-insecure-origin-as-secure="https://example.com" for the same purposes
  • For WebDrivers, there's acceptInsecureCerts capability. It can allow self-signed or otherwise invalid certificates to be implicitly trusted by the browser.

That said, I'd like to see --accept-insecure-certs flag option, because deno already uses flags for a lot of things, including permissions.


My use-case: I'm using a corporate Windows laptop with network monitoring. AFAIK, all https requests are also monitored, so there's a custom SSL-certificate installed system-wide. So, most of the software, that uses system CA storage, works just fine. But some uses custom or bundled CA, and it seems like it's a case with deno. Anyway, it downloads deps just fine, but fails to perfprm any https request.

Issue created as a follow up to gitter conversation: December 18, 2018 1:24 PM

Most helpful comment

It looks like deno is now using the reqwest library, which claims:

By default, a Client will make use of system-native transport layer security to connect to HTTPS destinations. This means schannel on Windows, Security-Framework on macOS, and OpenSSL on Linux.

But I'm still getting certificate errors when behind a corporate proxy. It looks like deno is configured to use rustls-tls instead of default-tls or native-tls. I think that's why it's still not working. Is there a reason to not use default-tls or native-tls?

I'm looking here. Specifically this line:

reqwest = { version = "0.10.1", default-features = false, features = ["rustls-tls", "stream", "gzip"] }

Seems like you could just change it to

reqwest = { version = "0.10.1", default-features = false, features = ["native-tls", "stream", "gzip"] }

And that would fix it.

All 10 comments

Seems like it'd be better to allow adding new CA entries that requests would trust, no? Having this flag is probably fine in exceptional circumstances, but for any production system leaving this flag on all the time is a huge red flag.

I wonder if this ought to share a prefix i.e. --allow? Would it be added to DenoPermissions, would it be "upgradeable" at runtime?

Related: #1064

@eventualbuddha yes, I'd like to have that option too. I mean, for some non-production cases, it might be better to completely disable any checks. And later, you might want to add new CA entries when preparing the code for production.

@hayd I made more research on that because I need to make it work already. So, I discovered, that these checks are performed in rustls. And as far as I can tell, we'll be unable to disable certificate checks, or add custom CA's unless this lib is built with "dangerous_configuration" feature turned on. After enabling it, we can create Connector with custom ClientConfig that has custom ServerCertVerifier. It should be done in //src/http_util.rs -> fn get_client.
That said, I'm not sure is it a good idea at all, to always build deno with dangerous_configuration feature. It sounds... "dangerous" :) But also I don't like locking CAs using webpki-roots with static CAs list, which is used by rustls. I'm more then sure, that if @ry wants deno to be adopted by corporations, it might be really vital to at least add an option to support system CAs, so developers on machines with monitored traffic by an employer, can also develop with deno.
So, even tho, adding option for custom CAs will require building rustls with dangerous_configuration feature, I think we should consider doing so.

Back to @hayd questions, I might be wrong, but I think that ideally, deno should pick up system CAs instead of bundled CAs without any additional flags. AFAIK, it will be a more browser-like approach.
If @ry decides to go with the flag instead, I don't think that it should be a permission, but rather a configuration. If we take a look at Chromes behavior, it will allow visiting the website with a bad certificate after we choose to proceed, but all insecure requests from that page to other sources with bad certificates will fail without any prompts and there's no way to allow them in "upgradable" manner.

Please, let me know what do you think about it?

As an update to this, I have a working branch, and it works fine, but I'm not ready to open a PR yet. Anyway, it's my first time coding in rust, so I expect a lot of help from code review. Currently, the branch is here: https://github.com/Maxim-Mazurok/deno/tree/accept-insecure-certs and it adds --accept-insecure-certs flag support. It's not considered permission, and thus, not upgradable during run-time. Someone might find it helpful. Luckily, I'm no longer an employee of company where I had to use Windows laptop with custom CA certs and I'm back to my lovely personal CentOS laptop :) So that issue is not critical for me anymore, but still I want to finish what I've started in hope that it'll help somebody else to adopt deno for their project. And in case if anyone is looking for an employee in SF Bay Area, I'm open for new opportunities :)

Chiming in that the Go tls.Config kind of supports both strategies.

  1. An all-bets-off InsecureSkipVerify boolean that seems analogous to curl's -k
  2. More detailed configuration: A boatload of hooks and fields for trusting additional CAs, and actually providing callbacks for inspecting connections at runtime (e.g. GetConfigForClient). Lots more. Easily the nicest TLS experience I've ever worked with.

Docs here: https://golang.org/pkg/crypto/tls/#Config

We could start with something like number 1, but leave the door open for more granular configuration.

My biggest worry here is that TLS in rust is kind of rough as it stands. We will be bound to the underlying implementation chosen, but we should take care to avoid letting the underlying implementation leak into the TypeScript API.

My dream would be a Typescript interface that roughly maps onto what Go does, and each capability added would be a runtime escalation just like allow-network. But we can start simple, e.g.

export interface TLSConfig {
    // defaults to false
    insecureSkipVerify?: boolean;
}

It looks like deno is now using the reqwest library, which claims:

By default, a Client will make use of system-native transport layer security to connect to HTTPS destinations. This means schannel on Windows, Security-Framework on macOS, and OpenSSL on Linux.

But I'm still getting certificate errors when behind a corporate proxy. It looks like deno is configured to use rustls-tls instead of default-tls or native-tls. I think that's why it's still not working. Is there a reason to not use default-tls or native-tls?

I'm looking here. Specifically this line:

reqwest = { version = "0.10.1", default-features = false, features = ["rustls-tls", "stream", "gzip"] }

Seems like you could just change it to

reqwest = { version = "0.10.1", default-features = false, features = ["native-tls", "stream", "gzip"] }

And that would fix it.

Is there any update on this issue, because I am facing this error when calling internally hosted reviewboard api using fetch while on VPN.
The error I get is

error: Uncaught Http: error sending request for url (https://[CUSTOM_HOST]/api/users/): error trying to connect: tls handshake eof
    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
    at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)
    at async fetch ($deno$/web/fetch.ts:591:27)

deno --version

deno 1.0.2
v8 8.4.300
typescript 3.9.2

I'm not sure about a flag, but at least ConnectOptions should support ignoring SSL problems. Unless I'm missing something, there is currently no way to connect to a server with a self-signed certificate.

Would love to see something like this implemented, i'm trying to run integration tests for a web app to ensure serveTls works, but all fetch calls (to test the endpoint works) fail

There needs to be both a environment variable and a fetch option for this. The former should be chosen over an cli argument for cases when one does not have control of the arguments passed to deno, which certainly will be the case sometimes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

doutchnugget picture doutchnugget  路  3Comments

CruxCv picture CruxCv  路  3Comments

benjamingr picture benjamingr  路  3Comments

ry picture ry  路  3Comments

davidbarratt picture davidbarratt  路  3Comments