microsoft / microsoft/AzureStorageExplorer

Imported certificates are ignored when proxy source is System proxy (proxy setting silently switches networking stack)

Open
#9,145 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

:computer: linux :electric_plug: certs :gear: emulator :gear: proxy
Dominant language
No language data
Stars
452
Forks
92
Avg merge
15h 20m
Merged PRs (30d)
3

Description

Summary

Certificates imported via Edit -> SSL Certificates -> Import Certificates are only trusted by the Node networking stack. When the proxy source is set to System proxy, Storage Explorer routes requests through the Electron net (Chromium) stack instead, which does not consult imported certs. The result is a confusing ERR_CERT_AUTHORITY_INVALID / "Electron Net Error" against an endpoint whose certificate the user has already imported -- most visibly when working with an HTTPS Azurite emulator.

The proxy setting is effectively a hidden networking-stack switch, and the two stacks have different certificate-trust sources. This is especially painful on Linux, where the Electron/Chromium stack trusts the per-user NSS database (~/.pki/nssdb) rather than the OS CA bundle, so neither the in-app import nor a system-store install makes the cert take effect on that stack.

Environment
  • Storage Explorer 1.45.0 (repros structurally on prior versions)
  • Observed on Linux (snap), but the stack-selection logic is cross-platform
  • HTTPS Azurite container (self-signed cert, IP:127.0.0.1)
Steps to reproduce
  1. Start Azurite over HTTPS with a self-signed cert.
  2. In Storage Explorer, Edit -> SSL Certificates -> Import Certificates and import the cert. Restart.
  3. Set proxy source = System proxy (application.proxy.source = "systemProxy").
  4. Attach the local emulator and expand Blob Containers / Queues.

Expected: the node lists children (the cert was imported).
Actual: Unable to retrieve child resources -- ProducerError: Electron Net Error / net::ERR_CERT_AUTHORITY_INVALID.

Switching proxy source to Do not use proxy (none) makes it work immediately -- not because a proxy was bypassed, but because the request moves back onto the Node stack that trusts the imported cert.

Root cause

src/Standalone/app/main/Net/NetProvider.ts selects the networking stack purely from the proxy source:

const result = await makeRequest(
  args.options,
  process.env.STG_EXP_PROXY_SRC === "systemProxy" ? "electron" : "node",
  true);
  • systemProxy -> ElectronRequest (Electron net / Chromium). Trust source: OS store on Windows/macOS, NSS db on Linux. Does not see in-app imported certs.
  • Every other source (none default, environmentVariable, appConfig) -> NodeRequest (Node https). Trust source: syswide-cas over userData/certs, i.e. the in-app imported certs (SslCertificateManagerMain._loadTrustedCerts).

Imported certs are wired only into the Node stack, so they silently do nothing whenever the effective stack is Electron.

The asymmetric auto-recovery in the same file makes it worse. maybeRetryRequest only retries node -> electron:

if (requestUsed === "node" && shouldRetry) { // cert/notfound error on node -> retry via electron
  return await retryFailedRequestWithElectron(...);
}

and on success it persists the switch:

await ConfigurationManager.setConfiguration("application.proxy.source", "systemProxy");

There is no electron -> node fallback. So a user who hits a transient cert error on the Node stack can be auto-moved to systemProxy (the Electron stack), after which their imported cert no longer applies and there is no path back except manually changing the proxy source.

Impact
  • Imported certificates appear to "not work" for any user on System proxy, with an error that points at cert trust rather than the real cause (stack selection).
  • The auto-manage-proxy feature can strand users on the exact stack that ignores their imported cert.
  • On Linux the only ways to satisfy the Electron stack are adding the cert to the snap/user NSS db (certutil -d sql:...nssdb -A -t "C,," ...) or launching with --ignore-certificate-errors -- neither is discoverable, and NSS trust is per snap-revision so it is lost on update.
Suggested directions
  • Feed imported certs into the Electron stack too (e.g. session.setCertificateVerifyProc / a verify handler that trusts userData/certs), so import works regardless of proxy source.
  • Add an electron -> node cert-error fallback to mirror the existing node -> electron retry, and/or avoid auto-switching a user onto systemProxy when doing so would drop imported-cert trust.
  • At minimum, surface a clearer message distinguishing "cert not trusted by the active networking stack" from a genuine authority failure, and document the Linux NSS requirement.
Related
  • #7289 (auto-manage proxy expanded to ENOTFOUND -- confirms the node->electron auto-switch behavior)
  • #2859 (imported cert not honored -- open, overlapping symptom, different framing)
  • #7471 (Electron Net Error with HTTPS Azurite)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/Standalone/app/main/Net/NetProvider.ts and trace makeRequest and maybeRetryRequest, including how proxy source selects Electron or Node. Compare the suggested trust-handling and fallback directions before choosing an approach. Done means an imported certificate works with systemProxy for the HTTPS Azurite reproduction, without misleading stack-related errors or an unexplained persistent switch.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, node.js, typescript
Domain
desktop, networking, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.