← All posts

API & helpers

How JustZix injects code on CSP-strict pages

Some pages have a Content-Security-Policy so strict they will not run any script their author did not write. And yet JustZix can inject your JS there and hook the Output Console into the page's console.log. This article explains how — and why the first version could not.

What CSP is and why it gets in the way

Content-Security-Policy is an HTTP header by which a page declares where scripts may be loaded from. A typical strict policy is script-src 'self' — "only run scripts from my own domain". Such a policy blocks inline <script>: if you inject a <script>code...</script> tag into the DOM, the browser will not run it. This is how GitHub, banking dashboards and many corporate sites work.

The first approach — and a regression

An early version of the Output Console hook (v2.13.72–73) injected code exactly via an inline <script> appended to <head>. On ordinary pages it worked. On pages with script-src 'self' the browser silently rejected the script — the hook never attached, the Output Console stayed empty. That was a regression: a feature that worked "in the demo" failed exactly where a developer needs it most.

The fix — chrome.scripting.executeScript

The solution (v2.13.74) no longer injects a <script> tag. Instead the extension's service worker calls chrome.scripting.executeScript. That is the crucial difference: this script runs from the extension's privilege, not from page level. The page's CSP does not apply to it — the browser treats it as code from a trusted extension the user consented to at install time.

MAIN world versus ISOLATED world

An extension's content scripts live by default in an "isolated world" (ISOLATED) — they have their own window, separated from the page. That is safe, but useless when you want to hook into the page's real console.log or touch its global variables.

So the hook lands in the MAIN world — the same JavaScript context the page's own code lives in. There it can wrap console.log/warn/error, attach error and unhandledrejection listeners, and see exactly what the page sees.

A bridge between worlds — postMessage

The hook in the MAIN world captures logs, but the Output Console window itself is rendered by a content script in the ISOLATED world. The two worlds do not share variables — a bridge is needed. That bridge is window.postMessage:

  1. The MAIN-world hook intercepts a console.log entry.
  2. It serializes the arguments and calls window.postMessage with a tagged payload.
  3. The ISOLATED content script listens for message, filters by tag, and renders the entry in the Output Console window.

postMessage is one of the few channels that crosses the world boundary — and it does so without violating CSP, because it is not script execution, just message passing.

What this means in practice

The Output Console and JS injection work on pages where the classic inline-script trick would fail — GitHub, banking dashboards, corporate intranets with a hard CSP. You do not configure anything; the extension picks this path itself.

Limits — what CSP still will not allow

Update v3.2.0 — rules, actions and TEMP windows too

The mechanism above was about the Output Console hook — how the extension listens to the page's console.log. Executing your JS rules, actions and TEMP JS windows is a separate path — and it too used to work only on pages whose CSP allowed 'unsafe-eval'. In v3.2.0 we ported the same "layered strategy" to that second path: the order of attempts is chrome.userScripts.executenew Function<script src="blob:…">. Rules, actions and the JS pane / JS Console now run even on Facebook (via the blob fallback) and on fully CSP-strict sites (via userScripts after a one-time "Allow user scripts" opt-in). Full write-up: JustZix JavaScript rules now work even on Facebook, X and GitHub.

See also

Install JustZix — and inject code even where the page says "no".

Rate this post

No ratings yet — be the first.

Try it yourself

Install JustZix and paste any snippet from this article. Two minutes from zero to a working rule across all your devices.

Get JustZix

Features · How it works · Examples · Use cases