diff --git a/libs/playlist/shared/util/src/lib/source-display/source-display.spec.ts b/libs/playlist/shared/util/src/lib/source-display/source-display.spec.ts index d75a11155..9087243df 100644 --- a/libs/playlist/shared/util/src/lib/source-display/source-display.spec.ts +++ b/libs/playlist/shared/util/src/lib/source-display/source-display.spec.ts @@ -130,6 +130,15 @@ describe('sourceDisplayName', () => { ).toBe('Mine'); }); + it('reads a bracketed key that only starts like JSON as parameters', () => { + const url = `https://proxy.test/list?config=${encodeURIComponent( + '[password]=hunter2' + )}`; + expect(sourceDisplayName({ title: 'Mine hunter2', url })).toBe( + 'proxy.test' + ); + }); + it('keeps a name that only shares a letter with a decoded password', () => { // `%2542` is the password as written; decoded it is just `B`. const url = 'https://host.test/list?password=%2542'; diff --git a/libs/playlist/shared/util/src/lib/source-display/source-display.ts b/libs/playlist/shared/util/src/lib/source-display/source-display.ts index eb3e4fb9d..c10a71c45 100644 --- a/libs/playlist/shared/util/src/lib/source-display/source-display.ts +++ b/libs/playlist/shared/util/src/lib/source-display/source-display.ts @@ -108,8 +108,11 @@ function collectUrlSecrets( if (value === null) { return; } - if (/^\s*[{[]/.test(value)) { - visitJson(parseJson(value), 0); + // Only real JSON: `[password]=…` starts like it but is a parameter + // list, read below. + const json = /^\s*[{[]/.test(value) ? parseJson(value) : null; + if (json !== null && typeof json === 'object') { + visitJson(json, 0); return; } const nested = ABSOLUTE_URL.test(value.trim()) ? parseUrl(value) : null;