Skip to content

Let TLS sockets trust additional roots, as fetch() does #230

Description

@connorff

In v0.5.1, fetch() verifies servers against:

  • the Mozilla roots
  • the OS trust store
  • SSL_CERT_FILE

TCP sockets verify against the Mozilla roots only (webpki_roots::TLS_SERVER_ROOTS), which cloudflare-compat.md documents so that celld works on machines without /etc/ssl/certs. So a Worker can fetch() a server whose certificate comes from a private CA, but it can't open a TLS socket to it. That blocks database drivers such as pg, which upgrade with startTls().

Repro: serve HTTPS on localhost:8443 with a certificate from a private CA in ca.pem, then run this Worker with SSL_CERT_FILE=ca.pem celld dev:

import { connect } from "cloudflare:sockets";

export default {
  async fetch() {
    const viaFetch = await fetch("https://localhost:8443/").then((r) => r.status, (e) => e.message);
    const socket = connect({ hostname: "localhost", port: 8443 }, { secureTransport: "starttls" }).startTls();
    const viaSocket = await socket.opened.then(() => "ok", (e) => e.message);

    return Response.json({ viaFetch, viaSocket });
  },
};
  • Expected: { "viaFetch": 200, "viaSocket": "ok" }
  • Actual: { "viaFetch": 200, "viaSocket": "TLS handshake failed: invalid peer certificate: UnknownIssuer" }

Suggested fix: build the socket connector from the same roots as reqwest (native certs plus webpki), so SSL_CERT_FILE applies to every outbound TLS client. ws_client.rs builds its roots the same way and likely needs the same change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions