Skip to content

Comments

fix: early polyfill injection via onCommitted + CSP bypass#7

Closed
madmath wants to merge 1 commit intoigrigorik:mainfrom
madmath:fix/polyfill-early-injection
Closed

fix: early polyfill injection via onCommitted + CSP bypass#7
madmath wants to merge 1 commit intoigrigorik:mainfrom
madmath:fix/polyfill-early-injection

Conversation

@madmath
Copy link
Contributor

@madmath madmath commented Feb 19, 2026

Issue

I observed that the polyfill doesn't inject soon enough in the page lifecycle. Which doesn't guarantee tools would register.

Summary

  • Inject the WebMCP polyfill via webNavigation.onCommitted + chrome.scripting.executeScript with files:[] and injectImmediately: true, guaranteeing it runs before page scripts and bypasses strict page CSP
  • Keep the manifest content_scripts entry (world: MAIN, document_start) as a belt-and-suspenders fallback; the polyfill's own guard prevents double-init
  • Remove noisy duplicate log when both injection paths fire

Test plan

  • Load extension in Chrome, open a page with strict CSP (e.g. GitHub), verify navigator.modelContext is available in console
  • Serve the inline-script timing test page (<script> checking 'modelContext' in navigator at parse time), confirm available: true
  • All 473 unit/integration tests pass

🤖 Generated with Claude Code

…and bypass CSP

The manifest content_scripts entry (world: MAIN, document_start) can lose
the race against inline page scripts and may be wrapped as an ES module by
CRXJS in dev mode. Additionally, injecting via an ISOLATED world loader
with script.textContent is blocked by strict page CSP.

Add a webNavigation.onCommitted handler that injects the polyfill
programmatically via chrome.scripting.executeScript with files:[] and
injectImmediately: true. This bypasses page CSP and runs at
document_start-equivalent timing. The manifest entry is kept as a
belt-and-suspenders fallback; the polyfill's own guard prevents
double-initialization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@igrigorik
Copy link
Owner

@madmath huh, do you have a ~reliable way to repro this? Intuitively, the strategy in this PR should be strictly worse..

According to Google docs content scripts declared via manifest are the first to be injected, and should be executing before any executeScript call, etc. Manifest scripts are injected by the browser engine synchronously with document creation vs. much laxer contract for injectImmediately. This doesn't smell right.

@madmath
Copy link
Contributor Author

madmath commented Feb 20, 2026

You can repro with https://peroh.com, it has a script in the head which will look for window.navigator.modelContext and prior to this change, it's not available. Previous discussion online talks about this approach, which is probably why Claude picked it up. Let me know what you want to do!

@igrigorik
Copy link
Owner

igrigorik commented Feb 20, 2026

I can't reproduce this, the tools are coming up reliably here. Are you testing on local preview / staging?

@madmath sanity check: are you using latest version from main?

@madmath
Copy link
Contributor Author

madmath commented Feb 20, 2026

Annnnd... I can't reproduce. I was on latest (last commit Feb 17), not sure what happened. Glad it's fine now!

@madmath madmath closed this Feb 20, 2026
@igrigorik
Copy link
Owner

\o/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants