Firefox · Core
CVE-2026-2782
Logic Error in Core
Overview
Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
getPropertiesdevtools/client/netmonitor/src/components/request-details/RequestPanel.js |
modified | |
ifdevtools/client/netmonitor/src/components/request-details/RequestPanel.js |
modified | |
toggleRawRequestPayloaddevtools/client/netmonitor/src/components/request-details/RequestPanel.js |
modified | |
ifdevtools/client/netmonitor/src/utils/request-utils.js |
modified | |
fordevtools/client/netmonitor/src/utils/request-utils.js |
modified |
Files Changed
devtools/client/netmonitor/src/components/request-details/RequestPanel.jsdevtools/client/netmonitor/src/utils/request-utils.jsdevtools/client/netmonitor/test/browser_net_complex-params.jsdevtools/client/netmonitor/test/html_params-test-page.html
Patch
diff --git a/devtools/client/netmonitor/src/components/request-details/RequestPanel.js b/devtools/client/netmonitor/src/components/request-details/RequestPanel.js
index 9ff470f1a0c..0f652e108d3 100644
--- a/devtools/client/netmonitor/src/components/request-details/RequestPanel.js
+++ b/devtools/client/netmonitor/src/components/request-details/RequestPanel.js
@@ -124,30 +124,34 @@ class RequestPanel extends Component {
}
/**
- * Mapping array to dict for TreeView usage.
- * Since TreeView only support Object(dict) format.
- * This function also deal with duplicate key case
- * (for multiple selection and query params with same keys)
+ * This maps an array to a dictionary for TreeView usage,
+ * sincs the treeView only supports the Object(dict) format.
*
- * This function is not sorting result properties since it can
- * results in unexpected order of params. See bug 1469533
+ * This function also deals with the duplicate key scenario
+ * (i.e multiple selections and query params with same keys)
+ *
+ * Note: This is not sorting the result properties since it can
+ * result in an unexpected order of parameters. See bug 1469533
+ *
+ * @param {object[]} arrOfKeyValuePairs - An array of key-value pairs or form params.
+ * @param {string} arrOfKeyValuePairs[].name
+ * @param {string|Array} arrOfKeyValuePairs[].value
*
- * @param {object[]} arr - key-value pair array or form params
* @returns {object} Rep compatible object
*/
- getProperties(arr) {
- return arr.reduce((map, obj) => {
- const value = map[obj.name];
- if (value || value === "") {
- if (typeof value !== "object") {
- map[obj.name] = [value];
+ getProperties(arrOfKeyValuePairs) {
+ return arrOfKeyValuePairs.reduce((dict, { name, value }) => {
+ if (name in dict) {
+ const dictValue = dict[name];
+ if (!Array.isArray(dictValue)) {
+ dict[name] = [dictValue];
}
- map[obj.name].push(obj.value);
+ dict[name].push(value);
} else {
- map[obj.name] = obj.value;
+ dict[name] = value;
}
- return map;
- }, {});
+ return dict;
+ }, Object.create(null));
}
toggleRawRequestPayload() {
@@ -205,10 +209,9 @@ class RequestPanel extends Component {
// Form Data section
if (formDataSections && formDataSections.length) {
- const sections = formDataSections.filter(str => /\S/.test(str)).join("&");
component = PropertiesView;
componentProps = {
- object: this.getProperties(parseFormData(sections)),
+ object: this.getProperties(parseFormData(formDataSections)),
filterText,
targetSearchResult,
defaultSelectFirstNode: false,
diff --git a/devtools/client/netmonitor/src/utils/request-utils.js b/devtools/client/netmonitor/src/utils/request-utils.js
index 31f4bfe037d..564fdda28ab 100644
--- a/devtools/client/netmonitor/src/utils/request-utils.js
+++ b/devtools/client/netmonitor/src/utils/request-utils.js
@@ -83,7 +83,6 @@ async function getFormDataSections(
}
}
}
-
return formDataSections;
}
@@ -428,28 +427,29 @@ function parseQueryString(query) {
/**
* Parse a string of formdata sections into its components
*
- * @param {string} sections - sections of formdata joined by &
- * @return {Array} array of formdata params { name, value }
+ * @param {Array<string>} sections Array of sections of formdata
+ * e.g ["", "a=x&b=y", "c=z"]
+ * @return {Array<object>} Array of formdata params
+ * e.g [{ name: 'a', value: 'x' }, { name: 'b', value: 'y'}, { name: 'c', value: 'z'}]
*/
function parseFormData(sections) {
- if (!sections) {
+ if (!sections || !sections.length) {
return [];
}
-
- return sections
- .replace(/^&/, "")
- .split("&")
- .map(e => {
- const firstEqualSignIndex = e.indexOf("=");
- const paramName =
- firstEqualSignIndex !== -1 ? e.slice(0, firstEqualSignIndex) : e;
- const paramValue =
- firstEqualSignIndex !== -1 ? e.slice(firstEqualSignIndex + 1) : "";
- return {
- name: paramName ? getUnicodeUrlPath(paramName) : "",
- value: paramValue ? getUnicodeUrlPath(paramValue) : "",
- };
+ const formDataParams = [];
+ const searchStr = sections
+ // Filter out empty sections
+ .filter(str => /\S/.test(str))
+ .join("&");
+
+ const params = new URLSearchParams(searchStr);
+ for (const [key, value] of params) {
+ formDataParams.push({
+ name: getUnicodeUrlPath(key),
+ value: getUnicodeUrlPath(value),
});
+ }
+ return formDataParams;
}
/**
diff --git a/devtools/client/netmonitor/test/browser_net_complex-params.js b/devtools/client/netmonitor/test/browser_net_complex-params.js
index 7fcfcf88c26..a757211de2d 100644
--- a/devtools/client/netmonitor/test/browser_net_complex-params.js
+++ b/devtools/client/netmonitor/test/browser_net_complex-params.js
@@ -20,7 +20,7 @@ add_task(async function () {
store.dispatch(Actions.batchEnable(false));
// Execute requests.
- await performRequests(monitor, tab, 12);
+ await performRequests(monitor, tab, 13);
const requestListItems = document.querySelectorAll(
".network-monitor .request-list-item"
@@ -49,7 +49,7 @@ add_task(async function () {
await testRequestWithFormattedView(
monitor,
requestListItems[2],
- "?foo",
+ "foo",
"bar=123=xyz",
"?foo=bar=123=xyz",
1
@@ -92,6 +92,14 @@ add_task(async function () {
'{ "foo": "bar" }',
1
);
+ await testRequestWithFormattedView(
+ monitor,
+ requestListItems[12],
+ "__proto__",
+ "evil_value",
+ "__proto__=evil_value",
+ 1
+ );
await teardown(monitor);
});
diff --git a/devtools/client/netmonitor/test/html_params-test-page.html b/devtools/client/netmonitor/test/html_params-test-page.html
index 3d657a5e87e..a3a799b76a6 100644
--- a/devtools/client/netmonitor/test/html_params-test-page.html
+++ b/devtools/client/netmonitor/test/html_params-test-page.html
@@ -71,6 +71,7 @@
await get("baz", "?species=in=(52,60)");
await get("baz", "?a=&a=b");
await get("baz", "?a=b&a=c&d=1");
+ await post("baz", "", urlencoded, "__proto__=evil_value");
}
</script>
</body>
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/devtools/client/netmonitor/test/browser_net_complex-params.js b/devtools/client/netmonitor/test/browser_net_complex-params.js
index 7fcfcf88c26..a757211de2d 100644
--- a/devtools/client/netmonitor/test/browser_net_complex-params.js
+++ b/devtools/client/netmonitor/test/browser_net_complex-params.js
@@ -20,7 +20,7 @@ add_task(async function () {
store.dispatch(Actions.batchEnable(false));
// Execute requests.
- await performRequests(monitor, tab, 12);
+ await performRequests(monitor, tab, 13);
const requestListItems = document.querySelectorAll(
".network-monitor .request-list-item"
@@ -49,7 +49,7 @@ add_task(async function () {
await testRequestWithFormattedView(
monitor,
requestListItems[2],
- "?foo",
+ "foo",
"bar=123=xyz",
"?foo=bar=123=xyz",
1
@@ -92,6 +92,14 @@ add_task(async function () {
'{ "foo": "bar" }',
1
);
+ await testRequestWithFormattedView(
+ monitor,
+ requestListItems[12],
+ "__proto__",
+ "evil_value",
+ "__proto__=evil_value",
+ 1
+ );
await teardown(monitor);
});
diff --git a/devtools/client/netmonitor/test/html_params-test-page.html b/devtools/client/netmonitor/test/html_params-test-page.html
index 3d657a5e87e..a3a799b76a6 100644
--- a/devtools/client/netmonitor/test/html_params-test-page.html
+++ b/devtools/client/netmonitor/test/html_params-test-page.html
@@ -71,6 +71,7 @@
await get("baz", "?species=in=(52,60)");
await get("baz", "?a=&a=b");
await get("baz", "?a=b&a=c&d=1");
+ await post("baz", "", urlencoded, "__proto__=evil_value");
}
</script>
</body>
Loading diff…
References
On This Page