fix: harden trust-bearing window globals and gate script loading#9330
Merged
fix: harden trust-bearing window globals and gate script loading#9330
Conversation
Follow-up to #9318. Extends the frozen first-party marker pattern to `__MARIMO_STATIC__` (backs the virtual-file allowlist) and `__MARIMO_MOUNT_CONFIG__`, and adds a shared `hasTrustedNotebookContext()` predicate so `RenderHTML.replaceSrcScripts` refuses notebook-authored `<script src>` in untrusted edit mode before any user interaction.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
peter-gy
reviewed
Apr 23, 2026
Comment on lines
+12
to
+29
| function isMarimoStaticState( | ||
| value: unknown, | ||
| ): value is Readonly<MarimoStaticState> { | ||
| if (typeof value !== "object" || value === null) { | ||
| return false; | ||
| } | ||
| const candidate = value as MarimoStaticState; | ||
| if (typeof candidate.files !== "object" || candidate.files === null) { | ||
| return false; | ||
| } | ||
| if ( | ||
| candidate.modelNotifications !== undefined && | ||
| !Array.isArray(candidate.modelNotifications) | ||
| ) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } |
Contributor
There was a problem hiding this comment.
should we also validate that files is a string-to-string map, instead of only checking if it's an object?
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens marimo’s trust-bearing window globals used by exports/static notebooks and adds a shared trust predicate to prevent notebook-authored <script src> from being appended in untrusted edit mode prior to user interaction.
Changes:
- Emit
__MARIMO_STATIC__and__MARIMO_MOUNT_CONFIG__viaObject.defineProperty(..., { writable: false, configurable: false })andObject.freeze(...)to prevent post-emission mutation/redefinition. - Add
hasTrustedNotebookContext()(run-cell OR trusted export marker OR auto-instantiate OR read/app mode) and use it to gate script loading behavior. - Add/adjust frontend tests and update export template snapshots accordingly.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/_server/templates/snapshots/export1.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/snapshots/export2.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/snapshots/export3.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/snapshots/export4.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/snapshots/export5.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/snapshots/export6.txt | Snapshot update reflecting frozen __MARIMO_STATIC__ and __MARIMO_MOUNT_CONFIG__. |
| tests/_server/templates/data/index.html | Makes __MARIMO_MOUNT_CONFIG__ non-writable/non-configurable and frozen in the HTML fixture. |
| marimo/_server/templates/templates.py | Adds _static_state_block() to emit hardened __MARIMO_STATIC__ and uses it in static_notebook_template. |
| frontend/src/plugins/core/trusted-url.ts | Clarifies trust gating rationale for accepting safe data: virtual-file payloads. |
| frontend/src/plugins/core/sanitize.ts | Aligns sanitization trust signals with the trusted export marker (avoid sanitizing in trusted export contexts). |
| frontend/src/plugins/core/test/RenderHTML.test.ts | Adds tests asserting <script src> is dropped in untrusted edit mode and allowed in trusted contexts. |
| frontend/src/plugins/core/RenderHTML.tsx | Gates <script src> appending on hasTrustedNotebookContext(). |
| frontend/src/core/static/static-state.ts | Makes __MARIMO_STATIC__ readonly + adds runtime shape validation before treating the page as “static”. |
| frontend/src/core/static/export-context.ts | Adds hasTrustedNotebookContext() combining run-cell/export marker/auto-instantiate/read-mode trust signals. |
| frontend/src/core/static/tests/static-state.test.ts | Tests static-state shape validation logic. |
| frontend/src/core/static/tests/export-context.test.ts | Tests export-context shape validation and hasTrustedNotebookContext() behavior. |
| frontend/index.html | Makes __MARIMO_MOUNT_CONFIG__ non-writable/non-configurable and frozen in the main frontend template. |
peter-gy
approved these changes
Apr 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #9318. Extends the frozen first-party marker pattern to
__MARIMO_STATIC__(backs the virtual-file allowlist) and__MARIMO_MOUNT_CONFIG__, and adds a sharedhasTrustedNotebookContext()predicate so
RenderHTML.replaceSrcScriptsrefuses notebook-authored<script src>in untrusted edit mode before any user interaction.