Skip to main content

Security and Data Flow

This page documents the trust boundaries of the current Python for Excel implementation. It is intended for security reviewers, developers, and workbook authors handling sensitive data. For the runtime topology and lifecycle, see Architecture and Runtime.

The central rule is that Python for Excel has several distinct data paths. Avoid blanket claims such as “everything stays local” or “everything goes to the cloud.” The destination depends on which capability is used.

Data paths at a glance

ActivityData pathMain trust decision
Normal notebook calculationDeclared workbook values → Boardflare host → browser Python; published results return to Excel.Trust the workbook and notebook source you execute.
Notebook AI authoringUser prompt + context selected/supplied for the AI action → Boardflare AI endpoint → configured AI gateway/provider.Decide what notebook/workbook-derived context may leave the normal calculation path.
Notebook-authored API callsPython/browser HTTP request → destination chosen by notebook code.Trust the external service and its authentication/privacy boundary.
Package loadingPackage/runtime metadata or wheels may be fetched into the browser runtime.Trust the package source and dependency supply chain.
Workbook persistence/sharingExecutable notebook source is stored with the workbook.Treat the file as a document that can contain code.

Normal calculation, AI, arbitrary API calls, and package installation are different trust decisions even though they all originate from one notebook surface.

Normal workbook calculation

Workbook data reaches Python only through the declared workbook integration. bf.inputs() asks the host to resolve specific workbook references and materialize their values into the notebook runtime.

Notebook Python does not receive a general-purpose parent-window or Office.js workbook object from the public API. Published values and callable results return through the separate outputs capability and shared-runtime registry.

This architectural boundary reduces accidental access to unrelated workbook operations. It does not prove that authored Python or third-party packages are safe.

Separate-origin notebook boundary

The notebook executes inside an iframe served from a different network origin from the parent add-in in production.

The iframe currently uses:

sandbox="allow-scripts allow-same-origin"

allow-same-origin is required by the stock marimo/Pyodide runtime, so the trust boundary does not come from sandbox tokens alone. Isolation depends on a distinct notebook origin plus explicit connection validation.

Production serves the child from https://notebook.boardflare.com. The child is configured with the exact parent origin and fails closed when that parent information is missing or malformed. Parent code is not supposed to read the child iframe document directly.

Capability handshake

Source, input, and outputs connections are explicit capabilities. Before transferring a MessagePort, the parent validates the connection identity.

The current checks include:

  • the active iframe Window as the message source;
  • the exact configured child origin;
  • protocol version 1;
  • the active secure session ID;
  • the active secure nonce;
  • exactly one transferred MessagePort;
  • an allowed source, input, or outputs capability label;
  • a non-empty generation identifier for input/output models.

Stale sessions and generations cannot claim current input snapshots, publication registries, or function results. These are implementation-level defense-in-depth controls, not notebook APIs.

Workbook persistence integrity

Excel stores notebook source and the saved Edit/App opening preference in Boardflare Custom XML. The current record includes a schema version, source, SHA-256 source digest, internal opening mode, and save timestamp.

A save writes the record, reads it back, and verifies the stored source/metadata. If verification fails, the host attempts to restore the prior stored value.

This is a persistence integrity check. It is not a digital signature and does not establish who authored or approved the notebook.

Current storage limits are:

ItemLimit
Notebook source200,000 UTF-8 bytes
Complete notebook XML1,000,000 bytes

See Getting Started: saving and reopening for the user workflow.

Uploaded source is staged before it is trusted as durable

Loading a Marimo .py file does not immediately replace the workbook copy.

The staged notebook starts in a fresh Edit session. Until Marimo Save reaches verified workbook persistence, Restore saved notebook can discard the staged replacement and return to the last workbook copy. This design reduces the chance that simply opening a bad .py file destroys the durable notebook source.

It does not make uploaded Python trustworthy: the staged source is still executable code once the notebook session starts it.

Executable workbook trust

Notebook source can execute when a workbook starts the notebook runtime, including cold starts driven by worksheet formulas and workbooks saved to open in App mode.

Treat a notebook-enabled workbook like any file that can contain executable logic:

  • open it only from a source you trust;
  • review package imports and external HTTP calls before using sensitive data;
  • do not treat App mode as source protection;
  • do not treat iframe isolation as proof that arbitrary Python is harmless;
  • revalidate important workbooks after material source or dependency changes.

App mode changes presentation. It is not a sandbox or an authorization boundary.

Notebook AI eligibility

Notebook AI is separate from the normal calculation path. The parent enables the Marimo AI UI only when Office SSO provides both:

  1. an Office auth token; and
  2. a tenant ID that is not Microsoft's personal-account tenant.

Personal Microsoft accounts, anonymous sessions, and unresolved identities receive the notebook with AI disabled. Normal bf.inputs(), bf.publish(), BF.OUTPUT(), and BF.FUNCTION() operation does not depend on this eligibility branch.

The existing Office SSO bearer token is passed in memory into Marimo's runtime auth configuration. The Boardflare AI endpoint independently requires the bearer token and checks the token payload's tid before forwarding an eligible request.

Current server-side validation scope

The endpoint's tenant check is intentionally a lightweight incremental control. It decodes the bearer token payload to inspect tid, but does not currently validate the token signature, issuer, audience, or expiry.

That limitation should be included in technical security reviews. The current control is an account-eligibility gate, not a complete server-side validation of Microsoft identity tokens.

AI authoring data flow

Depending on the Marimo action and the context the author selects or supplies, an AI request can include:

  • prompt and conversation text;
  • notebook code or selected code;
  • cell outputs;
  • variable previews or names;
  • schema or @ context;
  • image/file context supported by the authoring UI;
  • workbook-derived information already present in notebook state or selected context.

The request goes to Boardflare's AI endpoint and then through the configured AI gateway/provider path. The AI endpoint does not receive notebook execution tools and cannot directly mutate the live Python runtime; it returns authoring output that becomes ordinary source when the user accepts or applies it.

Current endpoint bounds include:

AI boundaryCurrent value
Complete request body2 MiB
Supplementary notebook/context text256 KiB characters before truncation
Default completion/chat output budget4,096 tokens
Inline-completion output budget1,024 tokens

The non-inline output budget can be configured in deployment; the table documents the current default.

See AI Authoring for the end-user workflow and context guidance.

Notebook-authored network requests

Python code can make browser-compatible HTTP requests. That path is controlled by the notebook author, not by the bf.inputs()/bf.publish() workbook bridge.

When code sends workbook-derived information to an external API:

  • the data leaves the workbook/browser runtime;
  • the destination service's privacy and security terms apply;
  • browser CORS and authentication restrictions apply;
  • workbook recipients may need their own credentials;
  • secrets embedded in notebook source can travel with the workbook when it is shared.

Do not place credentials in notebook source on the assumption that App mode hides them.

Package loading and supply chain

The browser runtime can load packages from the Pyodide distribution and install compatible wheels using micropip. Package code or metadata may therefore be downloaded even when normal workbook calculation otherwise stays inside the browser runtime.

Package use adds two separate questions:

  1. Compatibility — does the package and its dependencies work in WebAssembly/browser Python?
  2. Trust — do you trust the package source, version, and transitive dependencies with the data available to the notebook?

Version important dependencies where practical and review package behavior for sensitive workflows. See Building Notebooks: packages and environment.

Excel versus the public browser demo

The public demo uses Univer as its spreadsheet host. It shares the Boardflare notebook and capability concepts, but its persistence and custom-function lifecycle differ from Excel.

Do not use the browser demo as evidence that Excel-specific controls such as Custom XML persistence, Office SSO AI eligibility, or shared-runtime cold start behave correctly. Validate those paths in the actual Excel add-in.

Threat-model boundary

The current design aims to keep spreadsheet capabilities explicit, scoped, and validated across the notebook iframe boundary. It does not promise that arbitrary Python, arbitrary third-party packages, arbitrary workbooks, or arbitrary external services are safe.

A security review should separately evaluate:

  1. runtime boundary controls — origins, session/nonce identity, capability labels, generations, and message ports;
  2. workbook/source trust — what Python code will execute and who supplied it;
  3. persistence integrity — whether the intended source was durably saved and verified;
  4. external data paths — AI, authored APIs, packages, and credentials;
  5. business-logic correctness — whether the analysis itself is appropriate for its intended decisions.

For the detailed lifecycle behind these controls, see Architecture and Runtime.