From 480fdf86f746f4152c4b4338517b053924b9ea12 Mon Sep 17 00:00:00 2001 From: kagura-agent Date: Sat, 18 Apr 2026 07:47:09 +0800 Subject: [PATCH] Matrix: forward allowPrivateNetwork config to MatrixClient ssrfPolicy When createMatrixClient received allowPrivateNetwork=true but no explicit ssrfPolicy, the MatrixClient was created without SSRF policy, blocking connections to homeservers on private IPs (192.168.x.x, localhost). Derive ssrfPolicy from allowPrivateNetwork when no explicit policy is provided, using ssrfPolicyFromDangerouslyAllowPrivateNetwork. Fixes #68299 --- .../src/matrix/client/create-client.test.ts | 55 +++++++++++++++++++ .../matrix/src/matrix/client/create-client.ts | 4 +- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/extensions/matrix/src/matrix/client/create-client.test.ts b/extensions/matrix/src/matrix/client/create-client.test.ts index 4a2b28105a3..108ab0ce489 100644 --- a/extensions/matrix/src/matrix/client/create-client.test.ts +++ b/extensions/matrix/src/matrix/client/create-client.test.ts @@ -86,6 +86,61 @@ describe("createMatrixClient", () => { }); }); + it("derives ssrfPolicy from allowPrivateNetwork when no explicit policy is provided", async () => { + await createMatrixClient({ + homeserver: "https://matrix.example.org", + userId: "@bot:example.org", + accessToken: "tok", + persistStorage: false, + allowPrivateNetwork: true, + }); + + expect(MatrixClientMock).toHaveBeenCalledWith( + "https://matrix.example.org", + "tok", + expect.objectContaining({ + ssrfPolicy: { allowPrivateNetwork: true }, + }), + ); + }); + + it("prefers explicit ssrfPolicy over allowPrivateNetwork", async () => { + const explicitPolicy = { allowPrivateNetwork: true, customField: "test" }; + await createMatrixClient({ + homeserver: "https://matrix.example.org", + userId: "@bot:example.org", + accessToken: "tok", + persistStorage: false, + allowPrivateNetwork: false, + ssrfPolicy: explicitPolicy as never, + }); + + expect(MatrixClientMock).toHaveBeenCalledWith( + "https://matrix.example.org", + "tok", + expect.objectContaining({ + ssrfPolicy: explicitPolicy, + }), + ); + }); + + it("leaves ssrfPolicy undefined when allowPrivateNetwork is falsy and no explicit policy", async () => { + await createMatrixClient({ + homeserver: "https://matrix.example.org", + userId: "@bot:example.org", + accessToken: "tok", + persistStorage: false, + }); + + expect(MatrixClientMock).toHaveBeenCalledWith( + "https://matrix.example.org", + "tok", + expect.objectContaining({ + ssrfPolicy: undefined, + }), + ); + }); + it("skips persistent storage wiring when persistence is disabled", async () => { await createMatrixClient({ homeserver: "https://matrix.example.org", diff --git a/extensions/matrix/src/matrix/client/create-client.ts b/extensions/matrix/src/matrix/client/create-client.ts index c543308bd82..de872c55b9c 100644 --- a/extensions/matrix/src/matrix/client/create-client.ts +++ b/extensions/matrix/src/matrix/client/create-client.ts @@ -1,5 +1,6 @@ import fs from "node:fs"; import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher"; +import { ssrfPolicyFromDangerouslyAllowPrivateNetwork } from "openclaw/plugin-sdk/ssrf-policy"; import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime"; import type { SsrFPolicy } from "../../runtime-api.js"; import type { MatrixClient } from "../sdk.js"; @@ -95,7 +96,8 @@ export async function createMatrixClient(params: { idbSnapshotPath: storagePaths?.idbSnapshotPath, cryptoDatabasePrefix, autoBootstrapCrypto: params.autoBootstrapCrypto, - ssrfPolicy: params.ssrfPolicy, + ssrfPolicy: + params.ssrfPolicy ?? ssrfPolicyFromDangerouslyAllowPrivateNetwork(params.allowPrivateNetwork), dispatcherPolicy: params.dispatcherPolicy, }); }