dart-lang / http

A composable API for making HTTP requests in Dart.
https://pub.dev/packages/http
BSD 3-Clause "New" or "Revised" License
1.03k stars 358 forks source link

TLS is broken on fresh installed Windows - failed to trigger lazy loads of the root CA certs from Microsoft #1146

Open alexei-g-aloteq opened 8 months ago

alexei-g-aloteq commented 8 months ago

It seems to be a huge issue on Windows. I've spend many hours and can reproduce it 100% times.

How to reproduce:

  1. Create an empty app with HTTPs call using this package and address https://anything.cloudfunctions.net (or virtually any other property configured endpoint).
  2. Install a fresh Windows 10 or 11 (VM is fine, I've used a Qemu Proxmox hypervisor). I've used an official image from Microsoft for Windows 10 and 11 Home Edition. All updates are installed. Totally clean installation - no apps installed, no sites were opened.
  3. Build the test app for Windows.
  4. Run it on the test Windows machine.

Expected results:

  1. The call is successful.
  2. Inspect the User Certificates on Windows and see that appropriate root CA certificate is appeared in the Trusted Root Certificate Authorities section. Which means that the Windows root CA certificate lazy load works.

Real results:

  1. The call fails with error "Handshake error in client (OS Error: CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate(../../third_party/boringssl/src/ssl/handshake.cc:393))"
  2. Inspect the User Certificates on Windows and see that appropriate root CA certificate is NOT appeared in the Trusted Root Certificate Authorities. It means that calls from this package does not trigger the Windows root CA certificate lazy load.

How to prove that this the package issue:

  1. Run "curl https://anything.cloudfunctions.net" in cmd.exe.
  2. Restart the test app because BoringSSL does not load root CA certificates until recreated.
  3. Check the Expected Results (above) and see that call through Windows native SDK works as expected even for the same endpoint.

Please pay attention that this is not about:

  1. Not about self-signed or non-valid certificate.
  2. Not about expired X1 root certificate (aka Letsencrypt).
  3. Not about intermediate connection issues.

I know about a hack with a certificate pinning, but this is not an option since solves issues only with endpoints known at the moment of the building. This is obviously not an ultimate workaround.

There is an issue opened for almost a year: https://github.com/dart-lang/sdk/issues/52266

Appreciate your attention on this critical issue since we can clearly reproduce it on our projects.

alexei-g-aloteq commented 8 months ago

Anyone uses the http package on Windows at all?

maehata-fairy commented 1 month ago

I encountered a similar issue. While Invoke-RestMethod in PowerShell worked without any problems, using Dart’s Http started returning CERTIFICATE_VERIFY_FAILED unexpectedly one day.