docs(cache): document the cache signing trust model - #10526
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
All contributors have signed the CLA ✍️ ✅ |
There was a problem hiding this comment.
No issues found across 2 files
Architecture diagram
sequenceDiagram
participant User as User Config
participant Env as Environment
participant Proj as Project Config
participant NB as Notebook Metadata
participant Marimo as marimo Runtime
participant Cache as Cache Store
participant Crypto as Signing/Verification
Note over User,Crypto: Cache Signing Trust Model Architecture
Note over User,Env: Trusted Configuration Sources
User->>Marimo: signing.private_key_path
User->>Marimo: signing.trusted_signers
User->>Marimo: cache.verification (off|on|strict)
Env->>Marimo: cache.verification override
Note over Proj,NB: Untrusted Configuration Sources
Proj->>Marimo: cache.store (allowed)
Proj--xMarimo: signing (ignored)
Proj--xMarimo: cache.verification (ignored)
NB--xMarimo: signing (ignored)
NB--xMarimo: cache.verification (ignored)
Note over Marimo: Cache Read Flow
Marimo->>Cache: Request cached entry
Cache-->>Marimo: Return serialized data
alt verification = "on" (default)
Marimo->>Crypto: Verify signature with trusted key
Crypto->>Crypto: Check fingerprint whitelist
alt Trusted & valid signature
Crypto-->>Marimo: Signature valid
Marimo->>Marimo: Deserialize with pickle.loads
else Foreign key or invalid
Crypto-->>Marimo: Verification failed
Marimo->>Marimo: Treat as cache miss (recompute)
end
else verification = "strict"
Marimo->>Crypto: Verify signature with trusted key
Crypto->>Crypto: Check fingerprint whitelist
alt Trusted & valid signature
Crypto-->>Marimo: Signature valid
Marimo->>Marimo: Deserialize with pickle.loads
else Foreign key or invalid
Crypto-->>Marimo: Verification failed
Marimo->>Marimo: Raise exception (fail closed)
end
else verification = "off"
Marimo->>Marimo: Deserialize without verification
Note over Marimo: Unverified pickle.loads - code execution risk
end
Note over Marimo: Cache Write Flow
alt verification = "off"
Marimo->>Cache: Write unsigned entry
else verification = "on" or "strict"
Marimo->>Crypto: Sign entry with local Ed25519 key
Crypto-->>Marimo: Signature attached
Marimo->>Cache: Write signed entry
end
Note over Crypto: Missing cryptography package
alt cryptography not installed
Note over Marimo,Crypto: verification="on": all reads miss, writes skipped
Note over Marimo,Crypto: verification="strict": raises
end
295ce43 to
eab9543
Compare
There was a problem hiding this comment.
Pull request overview
Adds documentation describing marimo’s cache-signing trust model, including how signing keys are trusted across machines, how cache verification postures behave, and where security-sensitive settings can (and cannot) be configured.
Changes:
- Add a new “Cache signing and trust” section to the caching API docs, covering trust, sharing workflows, and
verificationpostures. - Update configuration docs to clarify that some security-sensitive settings cannot be overridden by repository-traveling config layers (e.g.,
pyproject.toml, script metadata, project.marimo.toml).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| docs/guides/configuration/index.md | Clarifies override limits and warns that repository-traveling layers can’t set signing / cache.verification. |
| docs/api/caching.md | Documents cache signing, key trust, verification modes, and where trust configuration is honored. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
eab9543 to
091e2bb
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
docs/api/caching.md:334
- The verification table implies entries are always signed on write for
verification="on"/"strict", but LazyLoader skips writes when no private signing key is available (e.g. a public-key-only verifier). This row should be qualified to avoid suggesting unsigned entries will be written under verifying modes.
| Foreign key, bad signature, or unsigned | served **unchecked** | **miss** — recomputed | **raises** |
| On write | not signed | signed | signed |
docs/api/caching.md:354
- This section says
[signing]and[cache].verificationare read from user config files only, but earlier in the same doc you describeMARIMO_CACHE_SIGNING_PRIVATE_KEY/MARIMO_CACHE_SIGNING_PUBLIC_KEYas additional (trusted, operator-controlled) ways to configure signing identity/trust. Consider clarifying that the restriction is about repository-controlled config layers, and that environment variables are still honored.
`[signing]` and `[cache].verification` are read from your own user configuration
only — the file at `~/.config/marimo/marimo.toml` or `~/.marimo.toml`. marimo
ignores them in `pyproject.toml`, in notebook script metadata, and in a
`.marimo.toml` that sits inside a project directory.
091e2bb to
bf80d22
Compare
bf80d22 to
a3982d4
Compare
a3982d4 to
a732d38
Compare
a732d38 to
84abef3
Compare
## 📝 Summary
Formalizes the caching config entrypoints, and adds "signing" fields for
cache verification.
This PR introduces the bones for signature verification that will come
in a subsequent change.
Cache configuration moves out of `experimental` into a top-level
`[cache]` table, and a `[signing]` table is added for trust and
identity:
```toml
[cache]
verification = "on" # off | on | strict
[cache.store]
type = "file"
args = { save_path = "~/.cache/marimo" }
# Or a tiered store:
# [[cache.store]]
# type = "file"
# [[cache.store]]
# type = "redis"
[signing]
private_key_path = "~/.marimo/key.pem"
[signing.trusted_signers]
"SHA256:kV9x2c...q8" = "CI cache key"
"SHA256:abc9f1...4d" = "Alice"
```
`[cache].verification` and `[signing]` are declared and merged here,
with followup providing implementation.
### Breaking
`experimental.cache` is removed for the explicit cache path.
### Notes
- `signing.trusted_signers` is a **replace** path in `merge_config`, not
a deep merge. Deep-merging unions the fingerprints from every layer, and
then no layer can remove a signer that a lower-priority one anchored.
- `signing.private_key_path` joins the secrets mask, so this machine's
signing identity is never serialized to the frontend.
### Stack
1. **this PR** — config entrypoints + signing fields
2. #10524 — `SigningPolicy`, `mode` -> `verification`
3. #10525 — config sanitization
4. #10526 — docs
84abef3 to
32d2111
Compare
32d2111 to
45b1cf7
Compare
Covers the config surface, the verification settings, and the framing that matters: trusting a fingerprint grants arbitrary code execution to whoever holds that key, because a cache restore is `pickle.loads`. There is no narrower cache-only version of the grant, so the docs say so plainly rather than leaving users to infer it. The section states its scope up front. Signing applies to `method="lazy"`; the default `method="pickle"` neither signs nor verifies, so a cache it wrote carries no provenance. Also documents which layers may set these settings and why the repository-controlled ones cannot, and corrects the `pythonpath` and `dotenv` sections: both are now read only from user configuration, and the `.env` beside a `pyproject.toml` is no longer loaded implicitly.
45b1cf7 to
02e01cc
Compare
📝 Summary
Docs for the cache signing trust model.
Adds a "Cache signing and trust" section to
docs/api/caching.mdcovering the config surface, theverification postures, and the sharing-between-machines workflow:
Stack
SigningPolicy,mode→verification