CVE-2025-5263
Overview
Background
- `DevToolsUtils.getProperty(obj, prop, invokeUnsafeGetters)`
- Reads a property from a debuggee object. The third argument controls whether unsafe getters (accessor properties backed by debuggee-defined functions) are actually invoked.
- Muted errors (`isMutedError`)
- When a script is loaded cross-origin without CORS, the engine “mutes” its errors: error details are hidden from the embedding page to prevent cross-origin information leaks. A
Debugger.ObjectexposesisMutedErrorto indicate this. - CWE-346 (origin validation error)
- Here, cross-origin error information that should be withheld from web content can be exposed if the error’s getters are invoked and the result is observable.
Root Cause Analysis
The Error previewer unconditionally invoked potentially unsafe getters for name and message: it called DevToolsUtils.getProperty(obj, "name", true) and getProperty(obj, "message", true), with the true flag forcing invocation of debuggee getters even when they are “unsafe” (a deliberate choice from Bug 1710694 so users could still see error text). But this ignored whether the error was a muted cross-origin error. For a muted error, name/message are exactly the cross-origin details the platform withholds; invoking the getters and feeding the result into the preview re-exposed information that same-origin policy had suppressed, enabling cross-origin leak attacks. Because the error-handling preview path was not isolated from web content’s muting state, an attacker could learn details of a cross-origin script error that should have been opaque.
The patch gates getter invocation on the mute flag. It computes const invokeUnsafeGetters = !obj.isMutedError; and passes that instead of a hard-coded true to both getProperty(obj, "name", invokeUnsafeGetters) and getProperty(obj, "message", invokeUnsafeGetters). For a muted error, invokeUnsafeGetters is false, so the unsafe getters are not called and no cross-origin error text is extracted; for ordinary (non-muted) errors behavior is unchanged. The advisory’s framing — “error handling for script execution was incorrectly isolated from web content, allowing cross-origin leak attacks” (CWE-346) — is substantiated precisely by the diff: the fix is an origin/mute-state check before surfacing error getters.
name/message getters, even on cross-origin muted errors whose details the platform deliberately hides, leaking them; the fix skips unsafe-getter invocation whenever isMutedError is set.Attack Path
- Attacker
Hosts a cross-origin script (loaded without CORS) that throws an error whose
name/messageare produced by getters encoding cross-origin-sensitive information. (UI:R per the vector) - Victim Loads attacker-controlled content that references the cross-origin script, so the engine produces a muted error object.
- Observation channel The error flows to a context where the DevTools object previewer runs on it and its preview becomes observable to the attacker’s measurement.
- Leak
Pre-patch, the previewer invokes the unsafe
name/messagegetters on the muted error and includes the result in the preview, exposing cross-origin error details. - Primitive Cross-origin information disclosure (reading error data the same-origin/mute policy should have withheld).
Impact Assessment
Files Changed
devtools/server/actors/object/previewers.js
Audit Directions
- Other `invokeUnsafeGetters: true` call sitesAudit the DevTools previewers/actors for other places that force unsafe-getter invocation without consulting
isMutedErroror other cross-origin gating. - Muted-error handling across surfacesReview console, network, and error-reporting paths that read
name/message/stackfrom error objects to ensure they honor muting consistently. - Debugger.Object cross-origin flagsConfirm all consumers of
Debugger.Objectthat render content check the relevant isolation flags (isMutedError, and related same-origin indicators) before exposing debuggee-controlled values.
Patch
diff --git a/devtools/server/actors/object/previewers.js b/devtools/server/actors/object/previewers.js
index 3fd4ec0122e..1c5052fe0f8 100644
--- a/devtools/server/actors/object/previewers.js
+++ b/devtools/server/actors/object/previewers.js
@@ -1034,10 +1034,13 @@ previewers.Object = [
const { obj } = objectActor;
- // The name and/or message could be getters, and even if it's unsafe, we do want
- // to show it to the user (See Bug 1710694).
- const name = DevToolsUtils.getProperty(obj, "name", true);
- const msg = DevToolsUtils.getProperty(obj, "message", true);
+ // The name and/or message could be getters, and even if it's unsafe,
+ // we do want to show it to the user, unless the error is muted
+ // (See Bug 1710694).
+ const invokeUnsafeGetters = !obj.isMutedError;
+
+ const name = DevToolsUtils.getProperty(obj, "name", invokeUnsafeGetters);
+ const msg = DevToolsUtils.getProperty(obj, "message", invokeUnsafeGetters);
const stack = DevToolsUtils.getProperty(obj, "stack");
const fileName = DevToolsUtils.getProperty(obj, "fileName");
const lineNumber = DevToolsUtils.getProperty(obj, "lineNumber");