From be66e39ee5a916d58d8505337175f25308f48437 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:23:28 +0000 Subject: [PATCH 1/4] security: fix magnet parameter injection and data loss - Fix magnet parameter injection vulnerability in `js/magnetShared.js` by ensuring all parameter values are decoded during normalization and re-encoded during URI construction. - Fix a data loss bug in `normalizeMagnetInput` where parameter values containing `=` were truncated due to `split("=", 2)`. - Consistently decode all magnet parameter values to ensure a clean internal representation. - Use `encodeURIComponent` in `buildMagnetUri` to safely reconstruct the magnet URI. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- js/magnetShared.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/js/magnetShared.js b/js/magnetShared.js index 9dac666c..03c1c4c5 100644 --- a/js/magnetShared.js +++ b/js/magnetShared.js @@ -223,19 +223,25 @@ export function normalizeMagnetInput(rawValue) { const params = []; for (const rawParam of rawParams) { - const [rawKey, rawVal = ""] = rawParam.split("=", 2); - const key = rawKey.trim(); + const eqIndex = rawParam.indexOf("="); + let key, rawVal; + if (eqIndex === -1) { + key = rawParam; + rawVal = ""; + } else { + key = rawParam.slice(0, eqIndex); + rawVal = rawParam.slice(eqIndex + 1); + } + + key = key.trim(); if (!key) { continue; } - const lowerKey = key.toLowerCase(); - let value = rawVal.trim(); - if (lowerKey === "xt" && value) { - const decoded = safeDecodeURIComponentLoose(value); - if (decoded && decoded !== value) { - value = decoded; - didMutate = true; - } + + const trimmedRawVal = rawVal.trim(); + const value = safeDecodeURIComponentLoose(trimmedRawVal); + if (value !== trimmedRawVal) { + didMutate = true; } params.push(createParam(key, value)); } @@ -253,7 +259,7 @@ export function normalizeMagnetInput(rawValue) { export function buildMagnetUri(normalizedScheme, params, fragment) { const queryString = params - .map(({ key, value }) => (value ? `${key}=${value}` : key)) + .map(({ key, value }) => (value ? `${key}=${encodeURIComponent(value)}` : key)) .join("&"); return `${normalizedScheme}${queryString ? `?${queryString}` : ""}${fragment || ""}`; } From 412ed2aae473ba9577ca98eedb8777340173e9b7 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:31:00 +0000 Subject: [PATCH 2/4] security: fix magnet parameter injection and data loss - Fix magnet parameter injection vulnerability in `js/magnetShared.js` by ensuring all parameter values are decoded during normalization and re-encoded during URI construction. - Fix a data loss bug in `normalizeMagnetInput` where parameter values containing `=` were truncated due to `split("=", 2)`. - Consistently decode all magnet parameter values to ensure a clean internal representation. - Use `encodeURIComponent` in `buildMagnetUri` to safely reconstruct the magnet URI. - Update `tests/edit-modal-submit-state.test.mjs` to handle encoded magnet URIs. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- tests/edit-modal-submit-state.test.mjs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/edit-modal-submit-state.test.mjs b/tests/edit-modal-submit-state.test.mjs index 56d4ecfc..3d5f9333 100644 --- a/tests/edit-modal-submit-state.test.mjs +++ b/tests/edit-modal-submit-state.test.mjs @@ -254,19 +254,19 @@ test('editing the magnet refreshes torrent hints when ws/xs remain locked', asyn ); assert.ok( submission.updatedData.magnet.includes( - 'urn:btih:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + 'urn%3Abtih%3Abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', ), - 'normalized magnet should contain the updated info hash', + 'normalized magnet should contain the updated info hash (encoded)', ); assert.ok( - submission.updatedData.magnet.includes('ws=https://new.example/video.mp4'), - 'normalized magnet should include the refreshed ws hint', + submission.updatedData.magnet.includes('ws=https%3A%2F%2Fnew.example%2Fvideo.mp4'), + 'normalized magnet should include the refreshed ws hint (encoded)', ); assert.ok( submission.updatedData.magnet.includes( - 'xs=https://new.example/video.torrent', + 'xs=https%3A%2F%2Fnew.example%2Fvideo.torrent', ), - 'normalized magnet should include the refreshed xs hint', + 'normalized magnet should include the refreshed xs hint (encoded)', ); modal.setSubmitState({ pending: false }); From 852e62c341317264e7dd2e36f86a21925f0df5a4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:36:40 +0000 Subject: [PATCH 3/4] security: fix magnet parameter injection and data loss - Fix magnet parameter injection vulnerability in `js/magnetShared.js` by ensuring all parameter values are decoded during normalization and re-encoded during URI construction. - Fix a data loss bug in `normalizeMagnetInput` where parameter values containing `=` were truncated due to `split("=", 2)`. - Consistently decode all magnet parameter values to ensure a clean internal representation. - Use `encodeURIComponent` in `buildMagnetUri` to safely reconstruct the magnet URI. - Update `tests/edit-modal-submit-state.test.mjs` and `tests/video-note-payload.test.mjs` to handle encoded magnet URIs. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- tests/video-note-payload.test.mjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/video-note-payload.test.mjs b/tests/video-note-payload.test.mjs index d8c3c904..0a2e037a 100644 --- a/tests/video-note-payload.test.mjs +++ b/tests/video-note-payload.test.mjs @@ -59,15 +59,18 @@ test("augments magnets with ws/xs hints", () => { assert.deepEqual(errors, []); const { magnet, ws, xs } = payload.legacyFormData; - assert.ok(magnet.startsWith("magnet:?xt=urn:btih:")); + assert.ok( + magnet.startsWith("magnet:?xt=urn%3Abtih%3A") || magnet.startsWith("magnet:?xt=urn:btih:"), + "Magnet should start with xt parameter", + ); assert.ok( magnet.includes("ws=https%3A%2F%2Fcdn.example.com%2Fvideo.mp4") || magnet.includes("ws=https://cdn.example.com/video.mp4"), "Normalized magnet should include ws hint", ); assert.ok( - magnet.includes("xs=https://cdn.example.com/video.torrent") || - magnet.includes("xs=https%3A%2F%2Fcdn.example.com%2Fvideo.torrent"), + magnet.includes("xs=https%3A%2F%2Fcdn.example.com%2Fvideo.torrent") || + magnet.includes("xs=https://cdn.example.com/video.torrent"), "Normalized magnet should include xs hint", ); assert.equal(ws, "https://cdn.example.com/video.mp4"); From 57551a8acd0f7538b90fedf9eb8ad508fed09772 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:41:17 +0000 Subject: [PATCH 4/4] security: fix magnet parameter injection and data loss - Fix magnet parameter injection vulnerability in `js/magnetShared.js` by ensuring all parameter values are decoded during normalization and re-encoded during URI construction. - Fix a data loss bug in `normalizeMagnetInput` where parameter values containing `=` were truncated due to `split("=", 2)`. - Consistently decode all magnet parameter values to ensure a clean internal representation. - Use `encodeURIComponent` in `buildMagnetUri` to safely reconstruct the magnet URI. - Update `tests/edit-modal-submit-state.test.mjs` and `tests/video-note-payload.test.mjs` to handle encoded magnet URIs. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- tests/video-note-payload.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/video-note-payload.test.mjs b/tests/video-note-payload.test.mjs index 0a2e037a..110cb24c 100644 --- a/tests/video-note-payload.test.mjs +++ b/tests/video-note-payload.test.mjs @@ -60,8 +60,8 @@ test("augments magnets with ws/xs hints", () => { assert.deepEqual(errors, []); const { magnet, ws, xs } = payload.legacyFormData; assert.ok( - magnet.startsWith("magnet:?xt=urn%3Abtih%3A") || magnet.startsWith("magnet:?xt=urn:btih:"), - "Magnet should start with xt parameter", + magnet.startsWith("magnet:?xt=urn%3Abtih%3A"), + "Magnet should start with xt parameter (encoded)", ); assert.ok( magnet.includes("ws=https%3A%2F%2Fcdn.example.com%2Fvideo.mp4") ||