cloudflare / cloudflare/workerd

Improve TLS handshake errors surfaced to fetch()

Open
#5,286 2 comments 3 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

While having a look at this [issue](https://github.com/cloudflare/workers-sdk/issues/10947) reported in workers-sdk, I've pointed the url to eg. https://self-signed.badssl.com/ (serves self-signed/untrusted certificate) to reproduce the error and received this:

```
Error: internal error; reference = asv0lnabm9mht2l97b8uim0n
at async Object.fetch (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/src/index.ts:3:13)
at async jsonError (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts:22:10)
at async drainBody (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts:5:10)%
````

so the root cause (TLS trust failure) never reaches the user

**proposal:**

return a TypeError (or similar) including the TLS failure reason, e.g.

```
TypeError: TLS certificate validation failed; reason: self signed certificate.
If you're intercepting HTTPS locally, add the signing root certificate to NODE_EXTRA_CA_CERTS or SSL_CERT_FILE before running wrangler dev.
```

**proposed change [here](https://github.com/cloudflare/workerd/blob/main/src/workerd/api/http.c%2B%2B):**

In fetchImplNoOutputLock, detect when the kj::Exception message contains TLS peer's certificate is not trusted. When that happens:

```
} else if (exception.getDescription().contains("TLS peer's certificate is not trusted")) {
auto desc = exception.getDescription();
constexpr kj::StringPtr reasonPrefix = "reason = "_kj;
kj::StringPtr reason = ""_kj;
KJ_IF_SOME(pos, desc.find(reasonPrefix)) {
reason = desc.slice(pos + reasonPrefix.size());
}
if (reason.size() > 0) {
return JSG_KJ_EXCEPTION(FAILED, TypeError,
kj::str("TLS certificate validation failed; reason: ", reason,
". Disable the VPN/proxy or add its signing certificate to "
"NODE_EXTRA_CA_CERTS (or SSL_CERT_FILE) before running wrangler dev."));
}
return JSG_KJ_EXCEPTION(FAILED, TypeError,
kj::str("TLS certificate validation failed. Disable the VPN/proxy or add its signing "
"certificate to NODE_EXTRA_CA_CERTS (or SSL_CERT_FILE) before running "
"wrangler dev."));
```

I've done this change and built it locally which resulted with this error when fetching that same badssl url:

```
TypeError: TLS certificate validation failed; reason: self signed certificate. If you're intercepting HTTPS locally, add the signing root certificate to NODE_EXTRA_CA_CERTS or SSL_CERT_FILE before running wrangler dev.
at async Object.fetch (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/src/index.ts:3:13)
at async jsonError (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts:22:10)
at async drainBody (file:///Users/ainergiz/LocalStorage/Documents/cosmo-app/cf-request-error/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts:5:10)%
```

I think this can be a straightforward PR but wanted to post it here first.

I’ve also prepared a matching patch for workers-sdk that detects the same runtime log line and prints a concise hint in the terminal, so the issue is clear even on older workerd builds. Happy to post that PR once this one lands.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.