fix: additional pep 723 sanitization#10281
Conversation
Notebook (PEP 723) metadata embedded in a .py file is attacker-controllable
and is merged with the highest precedence over the operator's own user config.
The previous sanitizer only stripped a single key
(tool.marimo.runtime.auto_instantiate), so every other section passed through
unchecked.
That let a notebook override credential-affecting and traffic-affecting config
such as tool.marimo.ai.open_ai.base_url: marimo resolves the operator's
OPENAI_API_KEY from the environment as the fallback key for that overridden
base_url, so the next AI request would POST the operator's real key to an
attacker-controlled URL. The same shape applies to tool.marimo.mcp.*.url and
tool.marimo.completion.{api_key,base_url}.
Fix the root cause at the shared ScriptConfigManager choke point: permit only
an explicit safe set of cosmetic/editor sections (formatting, save, display,
keymap, diagnostics, lint, snippets, datasources) and drop everything else,
logging a warning per dropped section. The existing auto_instantiate strip is
retained as defense in depth.
Tests:
- test_script_config_manager_sanitizes_auto_instantiate updated to assert the
whole runtime section is now dropped.
- test_script_config_manager_drops_credential_affecting_sections covers
ai/mcp/completion/secrets/package_management/server being dropped while a
cosmetic section survives.
- test_script_config_manager_ai_base_url_does_not_override is a direct
regression for the ai.open_ai.base_url override.
…arly-return bug - Allowlist language_servers, sharing, venv, runtime, experimental, package_management (no credential/traffic-affecting vector once auto_instantiate and isolate_apps are separately stripped). - Add experimental.isolate_apps to the stripped-key list alongside runtime.auto_instantiate. - Fix sanitize_pyproject_dict returning early from the whole function when one key_path's intermediate segment was missing, which silently skipped every subsequent key_path (caught by adding the second stripped key above). - Update/add tests accordingly.
No behavior change: consolidate the attacker-controllable/highest-precedence explanation to a single location and remove narrate-the-next-line comments in the tests touched by the prior commit.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
All contributors have signed the CLA ✍️ ✅ |
|
@Grg0rry can you sign our CLA please? |
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Pull request overview
Hardens parsing of PEP 723 (“script” header) inline config by restricting which tool.marimo.* sections can be applied and by stripping additional sensitive keys, reducing the risk of attacker-controlled notebooks overriding operator config.
Changes:
- Fix
sanitize_pyproject_dict()to keep processing subsequent key paths even if an earlier path is missing intermediate segments. - Introduce a top-level allowlist for
tool.marimo.<section>in script metadata and apply it inScriptConfigManager. - Expand sanitization and add tests covering the new allowlist + additional stripped keys (
experimental.isolate_apps, credential/traffic-related sections).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
marimo/_config/reader.py |
Adds script-metadata allowlist and improves sanitization behavior for multiple key paths. |
marimo/_config/manager.py |
Applies allowlist + expanded sanitization when reading PEP 723 script config. |
tests/_config/test_reader.py |
Adds regression test ensuring sanitization continues after a missing intermediate path. |
tests/_config/test_manager.py |
Adds/updates tests asserting sensitive sections/keys are stripped while allowed config passes through. |
tool is a table per the pyproject.toml spec, but script metadata is raw, untrusted TOML a notebook author fully controls. A non-table tool value previously crashed with an opaque AttributeError several calls deep; both call sites now share one validated accessor.
Summary
Hardening of pep 723 config options