Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit d7c765d

Browse files
authored
Trust CA root certificates on Windows and NODE_EXTRA_CA_CERTS (#587)
* Use Node's root certificates on Windows `workerd`'s `trustBrowserCas` uses `SSL_CTX_set_default_verify_paths()` to enable the system trust store. Unfortunately, this doesn't work on Windows, meaning any HTTPS `fetch()` would fail, with an `unable to get local issuer certificate` error. This change passes the root certificates from Node's bundled CA store to `workerd` as `trustedCertificates` on Windows. Closes cloudflare/workers-sdk#3264 * Read extra trusted certificates from `NODE_EXTRA_CA_CERTS` Wrangler passes the Cloudflare root certificate using the `NODE_EXTRA_CA_CERTS` environment variable. This change loads CA certs from this variable, fixing HTTPS `fetch()`s with WARP enabled. This can also be used for trusting self-signed certificates. Closes cloudflare/workers-sdk#3218
1 parent 25c2edc commit d7c765d

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

packages/miniflare/src/plugins/core/index.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import assert from "assert";
22
import { readFileSync } from "fs";
33
import fs from "fs/promises";
4+
import tls from "tls";
45
import { TextEncoder } from "util";
56
import { bold } from "kleur/colors";
67
import SCRIPT_ENTRY from "worker:core/entry";
@@ -44,6 +45,25 @@ import {
4445
} from "./modules";
4546
import { ServiceDesignatorSchema } from "./services";
4647

48+
// `workerd`'s `trustBrowserCas` should probably be named `trustSystemCas`.
49+
// Rather than using a bundled CA store like Node, it uses
50+
// `SSL_CTX_set_default_verify_paths()` to use the system CA store:
51+
// https://github.com/capnproto/capnproto/blob/6e26d260d1d91e0465ca12bbb5230a1dfa28f00d/c%2B%2B/src/kj/compat/tls.c%2B%2B#L745
52+
// Unfortunately, this doesn't work on Windows. Luckily, Node exposes its own
53+
// bundled CA store's certificates, so we just use those.
54+
const trustedCertificates =
55+
process.platform === "win32" ? Array.from(tls.rootCertificates) : [];
56+
if (process.env.NODE_EXTRA_CA_CERTS !== undefined) {
57+
// Try load extra CA certs if defined, ignoring errors. Node will log a
58+
// warning if it fails to load this anyway. Note, this we only load this once
59+
// at process startup to match Node's behaviour:
60+
// https://nodejs.org/api/cli.html#node_extra_ca_certsfile
61+
try {
62+
const extra = readFileSync(process.env.NODE_EXTRA_CA_CERTS, "utf8");
63+
trustedCertificates.push(extra);
64+
} catch {}
65+
}
66+
4767
const encoder = new TextEncoder();
4868
const numericCompare = new Intl.Collator(undefined, { numeric: true }).compare;
4969

@@ -360,14 +380,17 @@ export function getGlobalServices({
360380
bindings: serviceEntryBindings,
361381
},
362382
},
363-
// Allow access to private/public addresses:
364-
// https://github.com/cloudflare/miniflare/issues/412
365383
{
366384
name: "internet",
367385
network: {
386+
// Allow access to private/public addresses:
387+
// https://github.com/cloudflare/miniflare/issues/412
368388
allow: ["public", "private"],
369389
deny: [],
370-
tlsOptions: { trustBrowserCas: true },
390+
tlsOptions: {
391+
trustBrowserCas: true,
392+
trustedCertificates,
393+
},
371394
},
372395
},
373396
];

packages/miniflare/test/index.spec.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,16 @@ test("Miniflare: modules in sub-directories", async (t) => {
294294
const res = await mf.dispatchFetch("http://localhost");
295295
t.is(await res.text(), "123");
296296
});
297+
298+
test("Miniflare: HTTPS fetches using browser CA certificates", async (t) => {
299+
const mf = new Miniflare({
300+
modules: true,
301+
script: `export default {
302+
fetch() {
303+
return fetch("https://workers.cloudflare.com/cf.json");
304+
}
305+
}`,
306+
});
307+
const res = await mf.dispatchFetch("http://localhost");
308+
t.true(res.ok);
309+
});

types/env.d.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
declare namespace NodeJS {
22
export interface ProcessEnv {
33
NODE_ENV?: string;
4-
MINIFLARE_EXEC_NAME?: string;
5-
MINIFLARE_SUBREQUEST_LIMIT?: string;
6-
MINIFLARE_INTERNAL_SUBREQUEST_LIMIT?: string;
7-
MINIFLARE_TEST_REDIS_URL?: string;
4+
NODE_EXTRA_CA_CERTS?: string;
85
}
96
}

0 commit comments

Comments
 (0)