From a00e922d882538803e91235d3da12862de6b2e99 Mon Sep 17 00:00:00 2001 From: Project516 <138796702+Project516@users.noreply.github.com> Date: Tue, 27 Oct 2026 12:32:29 -0500 Subject: [PATCH 1/2] fix(shared): T3 Connect no longer runs cloudflared releases that trust the compromised eMudhra intermediates --- docs/internals/t3-connect.md | 6 ++++-- packages/shared/src/relayClient.test.ts | 23 +++++++++++++---------- packages/shared/src/relayClient.ts | 4 ++-- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/internals/t3-connect.md b/docs/internals/t3-connect.md index 6bf3ba74935f7..49a47d378e144 100644 --- a/docs/internals/t3-connect.md +++ b/docs/internals/t3-connect.md @@ -153,8 +153,10 @@ The version comes from running `cloudflared version`, not from the folder name. Connectors from before `--no-autoupdate` replaced themselves in place, so a managed folder can hold another release. Such a binary still runs as a fallback while the pin installs. Every binary needs `CLOUDFLARED_MIN_VERSION`, the oldest -release that accepts every flag the connector is started with. Raise it whenever -a new flag is added. +release that accepts every flag the connector is started with and rejects the +compromised eMudhra intermediates. No binary below it runs, even as a fallback, +so a host without an eligible one stays off the relay until it has one. Raise it +whenever a new flag or security fix needs it. ## OAuth traps diff --git a/packages/shared/src/relayClient.test.ts b/packages/shared/src/relayClient.test.ts index 0a987832ff749..38759a04f2d36 100644 --- a/packages/shared/src/relayClient.test.ts +++ b/packages/shared/src/relayClient.test.ts @@ -497,7 +497,7 @@ describe("RelayClient", () => { ), ); - it.effect.skipIf(windowsHost)("skips a PATH binary older than the minimum version", () => { + it.effect.skipIf(windowsHost)("skips binaries older than the minimum version", () => { const versions: Record = {}; return run( (baseDir) => @@ -506,7 +506,10 @@ describe("RelayClient", () => { const newPath = `${baseDir}/new/cloudflared`; yield* writeExecutable(oldPath); yield* writeExecutable(newPath); - versions[oldPath] = "2023.8.2"; + const managed = managedPathFor(baseDir, "2026.10.0"); + yield* writeExecutable(managed); + versions[managed] = "2026.10.0"; + versions[oldPath] = "2026.10.2"; versions[newPath] = RelayClient.CLOUDFLARED_MIN_VERSION; const manager = yield* RelayClient.makeCloudflaredRelayClient({ baseDir }); const env = { PATH: `${baseDir}/old:${baseDir}/new` }; @@ -536,7 +539,7 @@ describe("RelayClient", () => { Effect.gen(function* () { const overridePath = `${baseDir}/override/cloudflared`; yield* writeExecutable(overridePath); - versions[overridePath] = "2025.6.0"; + versions[overridePath] = "2026.10.2"; const manager = yield* RelayClient.makeCloudflaredRelayClient({ baseDir }); const env = { PATH: "", T3CODE_CLOUDFLARED_PATH: overridePath }; const withEnv = Effect.provideService( @@ -569,9 +572,9 @@ describe("RelayClient", () => { const newerServer = managedPathFor(baseDir, "2099.1.0"); versions[newerServer] = "2099.1.0"; yield* writeExecutable(newerServer); - versions[pathBinary] = "2026.9.3"; + versions[pathBinary] = "2026.10.3"; versions[older] = "2025.9.0"; - versions[newer] = "2026.1.0"; + versions[newer] = "2026.10.3"; yield* writeExecutable(pathBinary); yield* writeExecutable(older); yield* writeExecutable(newer); @@ -584,7 +587,7 @@ describe("RelayClient", () => { Effect.provideService(HostProcess.Environment, { PATH: `${baseDir}/bin` }), ); - expect(yield* resolveWith).toMatchObject({ source: "managed", version: "2026.1.0" }); + expect(yield* resolveWith).toMatchObject({ source: "managed", version: "2026.10.3" }); yield* writeExecutable(pinned); expect(yield* resolveWith).toMatchObject({ @@ -599,11 +602,11 @@ describe("RelayClient", () => { ).toEqual(["2026.1.0", RelayClient.CLOUDFLARED_VERSION, "2099.1.0"]); yield* fileSystem.remove(pinned); - expect(yield* resolveWith).toMatchObject({ source: "managed", version: "2026.1.0" }); + expect(yield* resolveWith).toMatchObject({ source: "managed", version: "2026.10.3" }); yield* fileSystem.remove(`${baseDir}/tools/cloudflared/2026.1.0`, { recursive: true, }); - expect(yield* resolveWith).toMatchObject({ source: "path", version: "2026.9.3" }); + expect(yield* resolveWith).toMatchObject({ source: "path", version: "2026.10.3" }); }), { versions }, ); @@ -618,7 +621,7 @@ describe("RelayClient", () => { (baseDir) => Effect.gen(function* () { const pinned = managedPathFor(baseDir, RelayClient.CLOUDFLARED_VERSION); - versions[pinned] = "2026.9.3"; + versions[pinned] = "2026.10.3"; yield* writeExecutable(pinned); const manager = yield* RelayClient.makeCloudflaredRelayClient({ baseDir }); const resolved = yield* manager.resolve; @@ -626,7 +629,7 @@ describe("RelayClient", () => { status: "available", executablePath: pinned, source: "managed", - version: "2026.9.3", + version: "2026.10.3", }); expect( resolved.status === "available" && RelayClient.isPinnedManagedRelayClient(resolved), diff --git a/packages/shared/src/relayClient.ts b/packages/shared/src/relayClient.ts index 5933ea7e6a09c..c5c0d7a82f3d6 100644 --- a/packages/shared/src/relayClient.ts +++ b/packages/shared/src/relayClient.ts @@ -25,8 +25,8 @@ import { isWindowsRenameLock } from "./atomicWrite.ts"; import * as HostProcess from "./HostProcess.ts"; export const CLOUDFLARED_VERSION = "2026.10.4"; -// Minimum for --output support; older connectors exit on that flag. -export const CLOUDFLARED_MIN_VERSION = "2025.6.1"; +// Minimum for --output support and the eMudhra fix, which 2026.10.2 macOS builds lack. +export const CLOUDFLARED_MIN_VERSION = "2026.10.3"; const CLOUDFLARED_PATH_ENV_NAME = "T3CODE_CLOUDFLARED_PATH"; const CLOUDFLARED_DOWNLOAD_TIMEOUT = "10 minutes"; From 61a396679454aeee944c49978c26b2a0504eabf0 Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Fri, 30 Oct 2026 01:16:12 +0000 Subject: [PATCH 2/2] test(shared): pin the cloudflared security boundary --- packages/shared/src/relayClient.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/relayClient.test.ts b/packages/shared/src/relayClient.test.ts index 38759a04f2d36..2c86930dbd7b7 100644 --- a/packages/shared/src/relayClient.test.ts +++ b/packages/shared/src/relayClient.test.ts @@ -510,7 +510,7 @@ describe("RelayClient", () => { yield* writeExecutable(managed); versions[managed] = "2026.10.0"; versions[oldPath] = "2026.10.2"; - versions[newPath] = RelayClient.CLOUDFLARED_MIN_VERSION; + versions[newPath] = "2026.10.3"; const manager = yield* RelayClient.makeCloudflaredRelayClient({ baseDir }); const env = { PATH: `${baseDir}/old:${baseDir}/new` }; expect(