# This Marimo Notebook Could Run a Command Before You Ran a Cell

> A fixed Marimo flaw let a crafted notebook start a local command when someone opened it for editing. The practical lesson is simple: notebook configuration belongs inside the code-review boundary.

- **Author:** Kubilay Tunca
- **Published:** 2026-08-26
- **Category:** For Developers
- **Tags:** Application Security, AI Agents, Security Engineering, Software Supply Chain
- **Canonical URL:** https://cyber-security-in-plain-english.com/post/developers/news/marimo-notebook-runs-before-cells

---

A developer downloads a Python notebook, opens it in edit mode, and pauses before running the first cell. That pause should be a safety boundary. In affected versions of Marimo, it was not.

A crafted notebook could place a command inside its Model Context Protocol server configuration. Marimo would start that command as a local subprocess while opening the file for editing, before the developer executed any notebook cell. The public record for CVE-2026-75149 says versions before 0.23.15 were affected and rates the flaw High, with a CVSS 4.0 score of 8.7 ([CVE Program record](https://www.cve.org/CVERecord?id=CVE-2026-75149); [VulnCheck](https://www.vulncheck.com/advisories/marimo-code-injection-via-mcp-server-configuration)).

Marimo had already shipped version 0.23.15 on 23 July 2026. The CVE was published on 19 August, and [The Hacker News brought the story to wider attention on 25 August](https://thehackernews.com/2026/08/marimo-notebook-flaw-could-run-mcp.html). As of 26 August, the CISA-added assessment attached to the CVE records no known exploitation. The record describes a fixed vulnerability with a useful design lesson, without evidence of a campaign against notebook users.

The lesson reaches well beyond Marimo. Modern notebooks can carry package requirements, editor settings, AI connections, tool definitions, and startup behaviour alongside code cells. Once configuration can create a process, configuration is code. Opening the file may be execution.

## The action happened on open, not on Run

Marimo is a reactive Python notebook system. Its notebooks can be stored as ordinary Python files, reviewed in Git, run as scripts, and opened in an interactive editor. That text-based design is useful because a team can diff a notebook instead of treating it as an opaque bundle. It also means one file can carry both visible program logic and metadata that changes how the editor prepares the session.

CVE-2026-75149 lived in that preparation path. According to the CVE record, an attacker could supply a crafted Model Context Protocol, or MCP, server entry with a command value embedded in the notebook. MCP is a common way to connect an AI application to external tools and data. A local MCP server is often launched as a process, so a server definition may legitimately include the command needed to start it.

That legitimate feature created the dangerous effect. When someone opened the notebook in edit mode, Marimo read its embedded configuration, merged that configuration into the active settings, and could launch the declared MCP command. The cells remained untouched. The subprocess had already started ([National Vulnerability Database](https://nvd.nist.gov/vuln/detail/CVE-2026-75149)).

The user interaction was therefore smaller than many developers would assume. The victim still had to obtain and open the crafted notebook. This was not described as an internet-wide, unauthenticated service compromise. Yet the expected decision point, running a cell, never arrived. A careful developer could inspect the visible cell body, decide not to execute it, and still be too late.

That distinction explains the severity without inflating the story. The CVE record assigns high confidentiality, integrity, and availability impact because the launched command runs locally with the user's authority. What it could read or change would depend on that account and environment. A laptop session with cloud credentials, package publishing tokens, database access, or a checked-out repository offers more reach than an empty disposable container.

No public source cited here reports exploitation in the wild. The CISA vulnerability enrichment attached to the record marked exploitation as none as of 21 August. Treat that as a current evidence limit, not a guarantee about the future. The correct response is to update and review exposure, without pretending every Marimo notebook has been hostile.

## The notebook carried a second program in its margins

Most developers understand that a Python file can execute code. The confusing part is timing. We have trained ourselves to look for the explicit act: run the script, execute the cell, start the application. Modern development files often perform work earlier, during setup.

A notebook may contain inline metadata following PEP 723, the Python specification for embedding script metadata in a source file. That metadata can describe dependencies and tool-specific settings. Marimo used settings under its own tool section to configure the editing environment. The file therefore carried two related programs: the code a developer could see in cells, and the instructions the host used to construct the session around those cells.

The patch makes that trust problem unusually clear. Marimo's fix added an allowlist for top-level configuration sections accepted from notebook metadata. The code comment says notebook metadata is attacker-controlled and merged with the highest precedence over the operator's own configuration. It specifically excludes settings that affect outbound traffic or credentials, including AI provider settings, MCP configuration, completion settings, secrets, and server settings ([Marimo patch commit](https://github.com/marimo-team/marimo/commit/1a21bd71e258438d2511136b5edacc94c08855f4)).

That comment is the heart of the incident. A portable document should be allowed to say how it prefers to be formatted or displayed. It should not silently replace the operator's AI endpoint, select a server command, redirect a credential-bearing connection, or change which network service starts. Those are authority-bearing settings.

This pattern appears throughout developer tooling. A repository can carry task definitions that start shell commands. An editor workspace can recommend extensions or define launch configurations. A package can contain an installation script. A CI file can request a privileged runner. A notebook can declare the process that supplies an AI tool. The visible artifact is data until the host interprets one of those fields as an action.

Calling all of it configuration hides the security distinction. Font size is configuration. A command path is execution authority. A remote endpoint can be credential-routing authority. A secret-provider setting can decide which identity becomes available to the session. They do not deserve the same trust merely because they share a TOML table.

The safe model is narrower: portable files may influence presentation and reproducibility, but they do not inherit the right to create processes, redirect credentials, or widen network access. If a workflow needs one of those effects, the operator should grant it through a separate, visible decision or a trusted project policy.

## Why an MCP setting could become a local process

The words “MCP server” can make this sound like an AI-model flaw. It was not. The model did not need to misunderstand a prompt or decide to attack its user. The vulnerable path sat in ordinary application code that turned a configuration value into a subprocess.

An MCP server exposes tools or data through a standard protocol. Some servers live on the network. Others run locally and communicate through standard input and output. To use a local server, the client needs to know what executable to start and which arguments to pass. A valid setup might launch a database helper, a documentation search service, or a project-specific tool bridge.

This is convenient because the client can bring the tool online when the session starts. It is dangerous when an untrusted file controls the launch instruction. The program doing the launching does not know whether the command came from the user's trusted settings or from a notebook downloaded five minutes ago unless it preserves that origin and applies a policy.

The Marimo patch chose a strong default. Instead of trying to recognise bad commands, it stopped notebook metadata from supplying the whole MCP section. That approach survives changes in command spelling, shell syntax, executable path, or payload. The file does not get to choose a process, so the application does not need to guess whether that process looks friendly.

The same patch removed other sensitive sections from script metadata. Its tests cover an AI base URL that could otherwise override the operator's provider and send an environment API key to another address. They cover MCP URLs, completion credentials, secrets, and server host settings. The fix also strips settings that could change behaviour without an explicit run action, while allowing less sensitive formatting and package-management preferences through ([Marimo pull request 10281](https://github.com/marimo-team/marimo/pull/10281)).

That split is more useful than a warning banner about malicious notebooks. Warnings ask a person to assess an arbitrary string while trying to get work done. An allowlist asks the software maintainers, once, which categories of setting a portable file is ever allowed to control. The result is easier to test and harder to click through.

There is still judgement involved. Package-management configuration can have security consequences, and organisations may choose stricter controls than an upstream product. The patch defines a product baseline, not every team's final policy. A research group opening public notebooks on credential-rich workstations should place another boundary around the whole session.

## “I did not run it” was the wrong audit question

Suppose a developer received a notebook during the affected period and says they opened it but never ran a cell. Before this disclosure, that answer might have closed the review. CVE-2026-75149 changes the question.

The first issue is whether the notebook was opened for editing with a Marimo version below 0.23.15. Version and action both matter. A vulnerable package sitting unused is different from a crafted file opened in the affected mode. An updated environment today does not prove that the same workstation was updated when the file was opened last month.

The second issue is what authority the Marimo process held at that time. Local command execution inherits practical reach from the surrounding session. Environment variables may contain provider keys. Home directories may contain cloud credentials, SSH material, package registry tokens, browser profiles, or source code. Mounted workspaces and active developer sessions turn a small trigger into a larger trust question.

The third issue is evidence. The absence of an executed notebook cell is not evidence that no process started. Teams should look for the notebook file, its embedded metadata, relevant shell or endpoint telemetry, child processes created by Marimo, network connections, modified files, and credential use around the open time. Available evidence will vary. Many laptops do not retain process ancestry for weeks, which is itself a useful finding about developer-workstation visibility.

Do not jump from a missing log to a confirmed compromise. Record the uncertainty. If a suspect notebook declared a process and the machine held valuable credentials, rotate the identities that process could realistically access and inspect their use. If no crafted metadata is present and the file came from a trusted internal source, the evidence supports a smaller response.

The disclosure date can mislead here. Version 0.23.15 shipped on 23 July, almost four weeks before the CVE became public on 19 August. A team that updated routinely may already be protected. Another team may have pinned 0.23.14 for reproducibility and remained exposed after the fixed release existed. Inventory answers that question; the calendar alone does not.

The public sources also do not claim that every pre-0.23.15 notebook launches a command. The file must contain the crafted sensitive configuration, and the user must open it in the relevant mode. Keep those conditions attached to the finding. Precision is what separates an incident review from a vulnerability headline.

## Updating is necessary, but the workflow still needs a boundary

The immediate product fix is straightforward: run Marimo 0.23.15 or later. The release was published on 23 July 2026, and the CVE lists every earlier version as affected ([Marimo 0.23.15 release](https://github.com/marimo-team/marimo/releases/tag/0.23.15)). Teams should verify the version in each environment that opens notebooks, including developer laptops, containers, remote workspaces, training images, and CI jobs.

A version check closes this specific path. It does not settle the larger risk of opening computational documents from outside the trust boundary. Notebooks are valuable precisely because they combine explanation, data access, dependencies, and executable work. That combination deserves the same intake discipline as a small repository.

Start with origin. A notebook from your own reviewed repository has a different history from an attachment, a public gist, a conference download, or a link in an issue. The source does not prove safety, but it tells you which review path applies. “It came from a colleague” is weak provenance if the colleague forwarded a file they did not inspect.

Next, separate inspection from execution. A plain text viewer or repository diff should be able to show the file before the notebook application constructs a live session. Review inline metadata as well as cell bodies. Search for tool sections, package sources, endpoints, commands, startup hooks, environment references, and settings that alter the host. A code review that collapses metadata or hides generated regions misses the part that may run first.

Then reduce what the first open can reach. Use a disposable workspace without personal cloud credentials, SSH agents, production database access, package publishing tokens, or broad network access. Mount only the files needed for the review. A container helps with filesystem isolation, but it is not a complete boundary if it inherits the host network, secrets, sockets, or home directory.

Network policy matters because a launched process may not need to damage the local machine to cause harm. Reading one credential and sending it out is enough. A review environment can deny outbound access by default, then allow specific package or data sources through a controlled route. The computer should not have a general way out merely because the notebook may need one library.

Finally, keep activation separate from portability. A project may legitimately need a local MCP server. Store the trusted server definition in an organisation-managed policy or a reviewed environment manifest, not in any notebook that happens to request it. The notebook can declare a logical capability, such as read-only access to a local dataset. A trusted layer decides which implementation, identity, and network rights satisfy that request.

This is the same distinction The Secure Harness makes for coding agents: bundling a model with every available tool creates the wrong unit. The useful unit is a task inside explicit boundaries. A notebook editor with AI integrations now belongs in that conversation.

## What engineering teams should do now

A calm response has two tracks. Close the known vulnerability everywhere, then test whether notebook intake relies on the same false assumption that opening is passive. The following sequence is designed for a working team, not a forensic lab with unlimited time.

1. **Inventory every Marimo environment.** Check local virtual environments, lockfiles, development containers, remote workspaces, teaching images, and automated jobs. Record the installed version rather than inferring it from a dependency file. Confirm 0.23.15 or later wherever notebooks can be opened.

2. **Update and rebuild pinned environments.** Change direct and transitive pins, regenerate lockfiles, rebuild images, and replace long-lived workspaces. Verify the version from inside the resulting environment. A merged dependency change does not protect a container that was never rebuilt.

3. **Find untrusted notebooks opened during the affected window.** Start with downloads, chat attachments, public repositories, support tickets, issue links, and shared drives. Ask whether each file was opened in edit mode with a vulnerable version. Preserve suspicious files before altering them so their metadata remains available for review.

4. **Review the metadata before the cells.** Inspect PEP 723 blocks and Marimo tool settings for MCP server commands, URLs, AI endpoints, completion settings, secrets, server configuration, and unexpected startup behaviour. Compare the file with its claimed upstream copy. A clean cell diff does not clear an altered metadata block.

5. **Scope authority on any affected machine.** List credentials, repositories, mounted directories, network routes, and local services available to the Marimo process when the file was opened. Look for child processes and outbound connections if telemetry exists. Rotate reachable secrets when the evidence and potential access justify it, not as a ritual disconnected from scope.

6. **Create a passive inspection path.** Let developers preview notebook source and metadata without starting the notebook host. Make that path the default for files crossing from email, public downloads, customer submissions, or unreviewed repositories. Document what reviewers should look for in ten minutes.

7. **Open unknown notebooks in a disposable environment.** Remove personal credentials, production access, SSH agent sockets, host home mounts, and general outbound network access. Grant data and package sources deliberately. Delete the environment after review rather than turning it into another long-lived workstation.

8. **Move tool activation into trusted policy.** Treat local MCP commands, remote tool endpoints, credential providers, and AI base URLs as administrator or project-owner settings. A notebook may request a capability, but an untrusted file should not select the executable or destination that receives authority.

9. **Add a regression test for the timing boundary.** Use a harmless fixture that includes a forbidden process-setting field and records whether anything starts when the notebook opens. The expected result is no subprocess before explicit approval. Run the test against future upgrades and any internal wrapper around the notebook environment.

10. **Teach one sentence, not a fear campaign.** Tell developers: “Previewing a computational document can construct an environment, so review its metadata as code.” That rule applies to notebooks, editor workspaces, build files, and agent tool definitions. It gives people a repeatable model instead of another file extension to fear.

The sequence should produce evidence. You should end with a version inventory, a list of files that crossed the trust boundary, a scoped response for any suspicious open, and a defined safe-open environment. If the exercise ends only with a company-wide message saying “be careful,” the technical boundary has not changed.

## The durable rule is about who may choose an effect

Marimo's patch did more than remove one key. It separated settings a portable notebook may influence from settings that can route credentials, create connections, or start processes. That is the right shape of fix because it asks who is allowed to choose an effect.

The notebook author may choose the analysis code they want to share. The recipient chooses whether to execute it. The product maintainer chooses safe defaults for opening it. The organisation chooses which identities and networks exist around the session. Trouble starts when a portable file silently takes one of those decisions for itself.

This is also why file scanning alone will never be enough. A scanner may recognise a suspicious command today. Tomorrow the same authority can hide behind another executable, remote endpoint, plugin, package hook, or helper service. Denying untrusted metadata the right to select those mechanisms is a stronger control than maintaining an endless dictionary of bad values.

There will be costs. A notebook that once configured its tools automatically may need a small setup step in a trusted project file. A disposable environment may take longer to start. A network rule may require an explicit package source. Those are honest costs in exchange for keeping document portability separate from workstation authority.

The story is narrow and the lesson is broad. CVE-2026-75149 affected Marimo before 0.23.15, required a crafted notebook to be opened, and has no publicly recorded exploitation as of 26 August 2026. The command could still start before the first cell. That one timing detail breaks the comfortable idea that opening a notebook is only reading.

Treat the margins as code. Put tool startup behind trusted policy. Make the first look genuinely passive.

For practical security guidance without the daily panic cycle, join the Cyber Security in Plain English newsletter. One email per month.

## Sources

- [CVE Program: CVE-2026-75149 record](https://www.cve.org/CVERecord?id=CVE-2026-75149), accessed 2026-08-26
- [National Vulnerability Database: CVE-2026-75149](https://nvd.nist.gov/vuln/detail/CVE-2026-75149), accessed 2026-08-26
- [VulnCheck: Marimo code injection via MCP server configuration](https://www.vulncheck.com/advisories/marimo-code-injection-via-mcp-server-configuration), accessed 2026-08-26
- [Marimo: Version 0.23.15 release notes](https://github.com/marimo-team/marimo/releases/tag/0.23.15), accessed 2026-08-26
- [Marimo: Patch commit for additional PEP 723 sanitisation](https://github.com/marimo-team/marimo/commit/1a21bd71e258438d2511136b5edacc94c08855f4), accessed 2026-08-26
- [Marimo: Pull request 10281, additional PEP 723 sanitisation](https://github.com/marimo-team/marimo/pull/10281), accessed 2026-08-26
- [The Hacker News: Marimo Notebook Flaw Could Run MCP Commands Before Cells Execute in Edit Mode](https://thehackernews.com/2026/08/marimo-notebook-flaw-could-run-mcp.html), accessed 2026-08-26

---

## About the author

Kubilay Tunca — Senior Full Stack Developer and Author. Founded Cyber Security in Plain English to translate complex security concepts into clear, practical advice, and writes the accompanying books on security, privacy, secure development, and AI systems.

## Books by this author

- **The Digital Fortress** — Your Everyday Guide to a Safer Digital Life. A warm, plain-English guide for people with real lives and finite patience. Learn the handful of habits that genuinely protect your money, accounts, and family, and get honest permission to ignore the rest. [Amazon](https://buy.cyber-security-in-plain-english.com/digital-fortress) · [Details](https://cyber-security-in-plain-english.com/books/the-digital-fortress)
- **The Anonymity Playbook** — Digital Survival for Whistleblowers, Journalists, Activists, and Everyone Else. A practitioner’s field manual for journalists protecting sources, whistleblowers, and activists. It explains how the surveillance actually works, what each technique costs you, and exactly where it fails. [Amazon](https://buy.cyber-security-in-plain-english.com/anonymity-playbook) · [Details](https://cyber-security-in-plain-english.com/books/the-anonymity-playbook)
- **Secure Software Development** — Practical patterns for building secure software. A hands-on security guide for developers and IT professionals who ship real software. Build, deploy, and maintain secure systems without slowing down or drowning in theory. [Amazon](https://buy.cyber-security-in-plain-english.com/secure-software-development) · [Details](https://cyber-security-in-plain-english.com/books/secure-software-development)
- **The Secure Harness** — Shipping Production Code with AI Coding Agents. A calm, practical guide to letting agents do useful work inside boundaries you set, enforce, and audit. Ships with 15 copy-pasteable artifacts: hook scripts, permission configs, release gates, and MCP templates. [Amazon](https://buy.cyber-security-in-plain-english.com/secure-harness) · [Details](https://cyber-security-in-plain-english.com/books/the-secure-harness)
- **The AI Native Engineer** — Build, Evaluate, and Ship AI Systems That Work in Production. Sixteen hands-on chapters, one real product. Grow it from a single model call into a retrieved, tool-using, observable, production-grade system, with evaluation treated as a habit from the first feature. [Amazon](https://buy.cyber-security-in-plain-english.com/ai-native-engineer) · [Details](https://cyber-security-in-plain-english.com/books/the-ai-native-engineer)

Full catalogue with contents and intended audience: https://cyber-security-in-plain-english.com/books

_As an Amazon Associate I earn from qualifying purchases. Buying through these links costs you nothing extra and helps pay for the blog._
