Skip to content

Conversation

@mochiya98
Copy link
Contributor

@mochiya98 mochiya98 commented Nov 25, 2025

Summary

fix #34268, close #29647 (duplicated)

The current implementation uses chrome.devtools.inspectedWindow.eval() , which can be blocked by a page's Content Security Policy (CSP). To handle this, I implemented a fallback mechanism that, if eval fails, attempts to evaluate the code in a Content Script.

Because Content Scripts do not have access to the Developer Tools Console API (e.g., inspect(), $0), some features (e.g. focusing a specified DOM node in the Elements panel) will remain unavailable.
However, this change still improves a situation where developer tools were completely unusable and will make many features available.

How to test

Please follow the reproduction steps from the original issue (#34268) to test behavior.

Note: when you reload the extension, tabs that were already open may not behave correctly. After loading the extension, open a new tab to test.

Detailed flow of operations

sequenceDiagram
    participant DevTools as DevTools Page<br>(main/index.js)
    participant Background as Background Script<br>(background/messageHandlers.js)
    participant CS as Content Script<br>[ExecutionWorld.ISOLATE]<br>(contentScripts/proxy.js)
    participant Page as Content Script<br>[ExecutionWorld.MAIN]<br>(contentScripts/fallbackEvalContext.js)
    
    alt First, attempt the regular processing
        DevTools->>DevTools: chrome.devtools.inspectedWindow.eval()
    else If it fails due to an error, run the fallback process below. (e.g. CSP Blocked)
        
        Note right of DevTools: Message:<br>{ source: 'devtools-page', payload: {<br>type: 'eval-in-inspected-window',<br>tabId, requestId, scriptId, args, } }
        DevTools->>Background: chrome.runtime.sendMessage()
        
        Note right of Background: Message:<br>{source: 'devtools-page-eval',<br>payload: { scriptId, args, } }
        Background->>CS: chrome.tabs.sendMessage()
        
        Note right of CS: Message:<br>{ source: 'react-devtools-<br>content-script-eval',<br>payload: { requestId, scriptId, args, } }
        CS->>Page: window.postMessage()
        
        Note over Page: Eval in Content Script<br>evalScripts[scriptId].apply(null, args);
        
        Note right of CS: Message:<br>{ source: 'react-devtools-<br>content-script-eval-response',<br>payload: { requestId, response, } }
        Page-->>CS: window.postMessage(Response)
        Note right of Background: Message:<br> response ( {result, error} )
        CS-->>Background: sendResponse()
        Note right of DevTools: { source: 'react-devtools-background',<br>payload: { type: 'eval-in-inspected-<br>window-response',<br>requestId, result, error, } }
        Background-->>DevTools: chrome.runtime.sendMessage()
    end
Loading

@meta-cla meta-cla bot added the CLA Signed label Nov 25, 2025
@hoxyq hoxyq self-requested a review November 25, 2025 12:43
Copy link
Collaborator

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. Overall approach looks sound.

Can you make sure all new files have the license header and @flow marker like the other files?

We should also make sure the script ID in fallbackEvalInInspectedWindow is typed to a literal to avoid typos while also adding runtime type-checking.

I'm leaning towards consolidating the source-as-string and source-as-js in a single file and let the bundler do the rest. That way it's harder to have both drift apart unintentionally. Does that make sense to you?

@mochiya98
Copy link
Contributor Author

Thank you.

That certainly seems like a good improvement.
I consolidated all eval processing into src/evalScripts.js, updated the callers, and added the license header and Flow definitions.

@mochiya98 mochiya98 requested a review from eps1lon November 27, 2025 08:18
@rearchitec
Copy link

@eps1lon @hoxyq +1 on this.
We can't use DevTools at all in our CSP-restricted environment.
This would be a significant improvement for enterprise users.
Is there anything blocking this?

@eps1lon eps1lon changed the title [DevTools] Fix developer tools not working in tabs restricted by CSP [DevTools] Enable minimal support in pages with sandbox Content-Security-Policy Jan 5, 2026
@eps1lon
Copy link
Collaborator

eps1lon commented Jan 5, 2026

Sorry for the delay. We had to deal with some urgent security vulnerabilities and then the holidays further delayed a response.

Validated that this works. What is unclear to me is why this works. chrome.devtools.inspectedWindow.eval allows running in the content script context via useContentScriptContext: true (https://developer.chrome.com/docs/extensions/reference/api/devtools/inspectedWindow). Isn't that the same as manually executing the code in a content script like this PR does? Feels like some unnecessary security ceremony on Chrome's part or a bypass of Content-Security-Policy: sandbox. @mochiya98 Can you explain the difference? Or does useContentScriptContext: true not work because it runs in the context of proxy.js which is isolated?

@mochiya98
Copy link
Contributor Author

mochiya98 commented Jan 6, 2026

To be honest, I don't have complete insight into Chrome's internals, but based on my testing with a simpler implementation using only a main world content script before this PR, it appears that useContentScriptContext: true always evaluates in the Isolated world regardless of the execution world type of the injected content scripts. So I don't think the presence of an Isolated world content script like proxy.js is relevant here. I also tried various values for contextSecurityOrigin, but it didn't change the behavior.

So while this implementation is more complex, I believe it's unavoidable due to Chrome's security constraints.

Copy link
Collaborator

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified with the provided repro and in random apps

@eps1lon eps1lon merged commit 583e200 into facebook:main Jan 13, 2026
234 checks passed
github-actions bot pushed a commit to code/lib-react that referenced this pull request Jan 17, 2026
github-actions bot pushed a commit to code/lib-react that referenced this pull request Jan 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DevTools Bug]: devtools does not works on null origin(sandbox) [DevTools Bug]: devtools does not works on null origin(sandbox)

3 participants