From a47c1536fcccd73ed7cdb89fff7d1c96d205b1b6 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Tue, 23 Jun 2026 11:34:47 +0200 Subject: [PATCH 1/3] Restrain logging of URL properties --- src/UrlParams.ts | 3 ++- src/utils/redact.test.ts | 36 ++++++++++++++++++++++++++++++++++++ src/utils/redact.ts | 17 +++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/utils/redact.test.ts create mode 100644 src/utils/redact.ts diff --git a/src/UrlParams.ts b/src/UrlParams.ts index f4ea840de..773aa4121 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -19,6 +19,7 @@ import { Config } from "./config/Config"; import { type EncryptionSystem } from "./e2ee/sharedKeyManagement"; import { E2eeType } from "./e2ee/e2eeType"; import { platform } from "./Platform"; +import { redact } from "./utils/redact"; interface RoomIdentifier { roomAlias: string | null; @@ -494,7 +495,7 @@ export const computeUrlParams = (search = "", hash = ""): UrlParams => { "intent:", intent, "\nproperties:", - properties, + redact(properties, "password"), "configuration:", configuration, ); diff --git a/src/utils/redact.test.ts b/src/utils/redact.test.ts new file mode 100644 index 000000000..a87a23690 --- /dev/null +++ b/src/utils/redact.test.ts @@ -0,0 +1,36 @@ +/* +Copyright 2026 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "vitest"; + +import { redact } from "./redact"; + +test("empty object", () => { + expect(redact({})).to.deep.equal({}); +}); + +test("no keys", () => { + expect(redact({ foo: "bar" })).to.deep.equal({ foo: "bar" }); +}); + +test("redact one key", () => { + expect(redact({ foo: "bar" }, "foo")).to.deep.equal({ foo: "" }); +}); + +test("redact two keys", () => { + expect(redact({ foo: "bar", bar: "foo" }, "foo", "bar")).to.deep.equal({ + foo: "", + bar: "", + }); +}); + +test("no redaction of unrelated keys", () => { + expect(redact({ foo: "bar", bar: "foo" }, "foo")).to.deep.equal({ + foo: "", + bar: "foo", + }); +}); diff --git a/src/utils/redact.ts b/src/utils/redact.ts new file mode 100644 index 000000000..7764aacb7 --- /dev/null +++ b/src/utils/redact.ts @@ -0,0 +1,17 @@ +/* +Copyright 2026 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +/** + * Redacts properties in the supplied object by replacing them with + * a constant value. + * @param obj Object in which to perform redaction + * @param keys Keys to be redacted in the object + * @returns A new object with the specified properties redacted + */ +export function redact(obj: T, ...keys: (keyof T)[]): T { + return { ...obj, ...Object.fromEntries(keys.map((k) => [k, ""])) }; +} From e7397a41db678694abd75da4e5c6c756073457f6 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Wed, 24 Jun 2026 13:35:44 +0200 Subject: [PATCH 2/3] Don't redact null or undefined --- src/utils/redact.test.ts | 22 ++++++++++++++++++++++ src/utils/redact.ts | 12 ++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/utils/redact.test.ts b/src/utils/redact.test.ts index a87a23690..6e9713faf 100644 --- a/src/utils/redact.test.ts +++ b/src/utils/redact.test.ts @@ -34,3 +34,25 @@ test("no redaction of unrelated keys", () => { bar: "foo", }); }); + +test("no redaction of missing keys", () => { + expect( + redact({ foo: "bar" } as { foo: string; bar: string | undefined }, "bar"), + ).to.deep.equal({ + foo: "bar", + }); +}); + +test("no redaction of null values", () => { + expect(redact({ foo: "bar", bar: null }, "bar")).to.deep.equal({ + foo: "bar", + bar: null, + }); +}); + +test("no redaction of undefined values", () => { + expect(redact({ foo: "bar", bar: undefined }, "bar")).to.deep.equal({ + foo: "bar", + bar: undefined, + }); +}); diff --git a/src/utils/redact.ts b/src/utils/redact.ts index 7764aacb7..9a3ea9090 100644 --- a/src/utils/redact.ts +++ b/src/utils/redact.ts @@ -12,6 +12,14 @@ Please see LICENSE in the repository root for full details. * @param keys Keys to be redacted in the object * @returns A new object with the specified properties redacted */ -export function redact(obj: T, ...keys: (keyof T)[]): T { - return { ...obj, ...Object.fromEntries(keys.map((k) => [k, ""])) }; +export function redact( + obj: T, + ...keys: (keyof T)[] +): Record { + const result: Record = { ...obj }; + for (const key of keys) + if (key in result && result[key] != null) { + result[key] = ""; + } + return result; } From 05176b10b14bcd1cf52905ec9828efdd105583a1 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Mon, 29 Jun 2026 14:32:49 +0200 Subject: [PATCH 3/3] Switch to jest-style assertions to please oxlint Signed-off-by: Johannes Marbach --- src/utils/redact.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/utils/redact.test.ts b/src/utils/redact.test.ts index 6e9713faf..977b5ebc0 100644 --- a/src/utils/redact.test.ts +++ b/src/utils/redact.test.ts @@ -10,26 +10,26 @@ import { expect, test } from "vitest"; import { redact } from "./redact"; test("empty object", () => { - expect(redact({})).to.deep.equal({}); + expect(redact({})).toEqual({}); }); test("no keys", () => { - expect(redact({ foo: "bar" })).to.deep.equal({ foo: "bar" }); + expect(redact({ foo: "bar" })).toEqual({ foo: "bar" }); }); test("redact one key", () => { - expect(redact({ foo: "bar" }, "foo")).to.deep.equal({ foo: "" }); + expect(redact({ foo: "bar" }, "foo")).toEqual({ foo: "" }); }); test("redact two keys", () => { - expect(redact({ foo: "bar", bar: "foo" }, "foo", "bar")).to.deep.equal({ + expect(redact({ foo: "bar", bar: "foo" }, "foo", "bar")).toEqual({ foo: "", bar: "", }); }); test("no redaction of unrelated keys", () => { - expect(redact({ foo: "bar", bar: "foo" }, "foo")).to.deep.equal({ + expect(redact({ foo: "bar", bar: "foo" }, "foo")).toEqual({ foo: "", bar: "foo", }); @@ -38,20 +38,20 @@ test("no redaction of unrelated keys", () => { test("no redaction of missing keys", () => { expect( redact({ foo: "bar" } as { foo: string; bar: string | undefined }, "bar"), - ).to.deep.equal({ + ).toEqual({ foo: "bar", }); }); test("no redaction of null values", () => { - expect(redact({ foo: "bar", bar: null }, "bar")).to.deep.equal({ + expect(redact({ foo: "bar", bar: null }, "bar")).toEqual({ foo: "bar", bar: null, }); }); test("no redaction of undefined values", () => { - expect(redact({ foo: "bar", bar: undefined }, "bar")).to.deep.equal({ + expect(redact({ foo: "bar", bar: undefined }, "bar")).toEqual({ foo: "bar", bar: undefined, });