master HEAD as of 2026-06-05 (latest released docs line).threat-model-producer rubric), for the Apache Zeppelin PMC to review.security@apache.org); findings that fall under §3 or §9 are closed citing this document.What Zeppelin is. Apache Zeppelin is a web-based, multi-user notebook server for interactive data analytics. Users open notebooks in a browser and run “paragraphs” of code against pluggable interpreters (Spark, Flink, Python, JDBC, shell, etc.); the Zeppelin server launches and talks to interpreter processes over a Thrift IPC channel and returns results to the browser over a websocket. Executing user-supplied code on the server is the product's primary function, not a vulnerability — the security model is about who is allowed to reach that capability and with what isolation, not about preventing code execution.
zeppelin-server) plus one or more interpreter processes; reached via HTTPshiro.ini, interpreter settings, zeppelin-site.xml, the host.Component-family table (maintainer — §14.8):
| Family | Entry point | Touches outside process? | In model? |
|---|---|---|---|
| Web/REST/websocket server | org.apache.zeppelin.rest.*, websocket | network | yes |
| AuthN/AuthZ (Shiro + notebook ACL + URL ACL) | shiro.ini, NotebookAuthorization, SecurityRestApi | filesystem (config) | yes |
| Interpreter launch + IPC | Thrift RemoteInterpreterServer, process launcher | child processes, network | yes (the launch/isolation boundary) |
| Interpreter-executed user code | %spark, %sh, %python, %jdbc, … | arbitrary (by design) | boundary only — the code is by-design; reaching/isolating it is in model |
| Credentials / datasource auth | CredentialRestApi, credential injection | filesystem, backends | yes |
| Notebook storage / repos | NotebookRepo (local FS, S3, Git, etc.) | filesystem / cloud | yes |
| Bundled interpreters / examples / web UI assets | *-interpreter modules, demos | varies | all bundled interpreters first-class for security purposes (§14.8); demo/example notebooks are a separate category |
%sh, Spark driver code, etc.) by design; Zeppelin does not attempt to confine what that code does on the host or backend. (maintainer — §14.3)The primary trust boundary is the authentication + authorization layer (Shiro realm → notebook ACL → URL ACL), not the API surface itself. Data flow and the trust transitions it crosses:
Reachability preconditions per family (the triager's first test):
shiro.ini, zeppelin-site.xml, credential stores, and the interpreter settings are trusted inputs written by the operator, not attacker-controllable.setuid- style user switching. It is not expected to run as root.This is the heart of Zeppelin's model — several defaults are the less-secure value, so the model is ambiguous until the PMC rules on each (see §14 wave 1):
| Knob | Default | Effect on model | Maintainer stance |
|---|---|---|---|
Shiro authentication (conf/shiro.ini) | absent → anonymous (documented) | No auth boundary at all; every §8 authn/authz property is void | dev-convenience (maintainer — §14.1): anonymous is not the supported posture; reports against an exposed anonymous instance are OUT-OF-MODEL: non-default-build |
zeppelin.notebook.public / ZEPPELIN_NOTEBOOK_PUBLIC | true → new notes public (documented) | Empty-ACL note is readable/runnable by any authenticated (or anonymous) user | by-design (maintainer — §14.2): public-by-default is intended; an empty-ACL note being readable/runnable is not a bug |
| Interpreter user impersonation | off → runs as server OS user (documented) | Without it, every run-capable user‘s code shares the *server’s* OS identity/privileges and filesystem | by-design (maintainer — §14.3): running as the server OS user is the documented default; OS isolation requires enabling impersonation |
| Interpreter binding mode (shared / scoped / isolated) | shared (maintainer — §14.4) | Process-level separation between users/notes; “isolated” is a stability/resource boundary, not a security sandbox | maintainer — §14.4: default is shared; no binding mode is a security sandbox |
URL ACLs ([urls] in shiro.ini) gating /interpreter, /credential, /configurations | not restricted unless operator adds them (documented) | Sensitive admin endpoints open to any authenticated role absent explicit [urls] rules | maintainer — §14.5: no built-in admin gate; protection relies entirely on shiro.ini [urls] |
HTTPS / security headers (http_security_headers) | off/plain unless configured (documented) | Credentials + session over plaintext; missing CSP/XFO | operator responsibility (§10); no CSP and Origin-based CSRF only — VALID-HARDENING (maintainer — §14.10) |
Insecure-default ruling (recorded). The PMC has ruled that every insecure §5a default above is a dev-convenience / by-design choice, not the supported production posture: Zeppelin's stance is “open by default, secure by configuration” (enable Shiro, or deploy only in a secured/trusted network). A report that only manifests under one of these defaults is therefore OUT-OF-MODEL: non-default-build (or BY-DESIGN), with the requirement living in §10. See §14 wave 1 for the per-knob answers.
Inputs and their trust (network-service shape — rows are endpoints/messages):
| Surface | Input | Attacker-controllable? | Caller/operator must enforce |
|---|---|---|---|
POST login / Shiro filter | credentials | yes (pre-auth) | strong realm config; lockout/rate-limit at proxy (inferred) |
| Websocket ops (run/edit/move paragraph) | notebook + paragraph payload | yes (authenticated user) | notebook ACL + run permission enforced server-side (documented) |
NotebookRestApi / InterpreterRestApi | note id, interpreter settings | yes (authenticated user) | URL ACL + ownership checks, enforced server-side (maintainer — §14.6) |
CredentialRestApi | per-user credentials | yes (authenticated user) | per-user credential isolation (maintainer — §14.7) |
| Paragraph code body | arbitrary code | yes — by design | this is the granted capability, not validated input |
shiro.ini, zeppelin-site.xml, interpreter JSON | config | no — operator-trusted | filesystem perms on config/secret files (inferred) |
| Notebook storage backend contents | persisted notes | mostly trusted (written via the app) | integrity of the repo (S3/Git/FS) (inferred) |
Size/shape/rate: (maintainer — §14.9) there is no rate limit and no concurrent-interpreter-launch cap today; the PMC treats this as VALID-HARDENING and welcomes the scan surfacing concrete limits.
In scope:
/interpreter, /credential) their role shouldn‘t, or (impersonation on) break out of their impersonation identity into another user’s or the server's.Capabilities: can send arbitrary HTTP/websocket traffic; can author arbitrary code in paragraphs they may run; cannot (assumed) read the operator's config/secret files or the host outside what their interpreter identity grants.
Explicitly out of scope:
shiro.ini / interpreter config / the host — they have already won.%sh rm -rf.Each conditional on the relevant §5a knob being set securely. The PMC has confirmed properties 1–5 below as committed properties (§14.5–§14.7), now tagged (maintainer); property 6 (resource/availability) is not a committed property today (§14.9).
[urls]. Violation symptom: a non-admin reaches /interpreter, /credential, or /configurations despite a restricting rule. Severity: high. (documented mechanism; maintainer — §14.5: no built-in admin gate, so this property holds only when the operator adds [urls] rules)VALID-HARDENING and welcomes concrete recommendations from the scan rather than suppressing them.shiro.ini, there is no authn/authz boundary; everything in §8 is void. (documented)False-friend properties (call out explicitly):
Well-known attack classes left to the operator/integrator: SSRF from interpreter code reaching internal services; secrets-in-notebooks; XSS/CSRF on the notebook web UI — (maintainer — §14.10) there is no Content-Security- Policy and CSRF protection is Origin-header-based only, so strengthening these (CSP, stronger CSRF) is welcome VALID-HARDENING; websocket cross-origin. The point is to put integrators on notice.
For Zeppelin the “user” is the operator deploying it:
[urls] rules restricting /interpreter, /credential, /configurations (and other admin paths) to admin roles. (documented)zeppelin.notebook.public=false if notebooks should default to private. (documented)http_security_headers. (documented)shiro.ini, credential stores, and notebook storage with host filesystem permissions; do not run the server as root. (inferred)/interpreter and /credential reachable by all authenticated users (no [urls] rules).The highest-leverage section for keeping scan output signal-heavy:
%sh / interpreter executes arbitrary shell or driver code → RCE.” By design for a run-capable user; OUT-OF-MODEL / BY-DESIGN unless it crosses a tenant or the operator boundary. (§3, §9) (maintainer — §14.3)shiro.ini. Out of model — auth is operator-enabled. (§5a, §9) (maintainer — §14.1)shiro.ini enabled, or notebook.public=false by default); adding a built-in sandbox for interpreter code; a new notebook-storage backend with different trust.| Disposition | Meaning | Licensed by |
|---|---|---|
VALID | Bypasses the authn/authz gate, or lets a user exceed their notebook/role grant, or crosses a tenant/credential/impersonation boundary, with auth configured. | §8, §6, §7 |
VALID-HARDENING | No §8 property broken, but the API makes a §11 misuse too easy; hardened at maintainer discretion. | §11 |
OUT-OF-MODEL: trusted-input | Requires control of operator config (shiro.ini, interpreter JSON, host). | §6 |
OUT-OF-MODEL: adversary-not-in-scope | Requires operator/admin privilege, or is a run-capable user executing code within their grant. | §7 |
OUT-OF-MODEL: non-default-build | Only manifests under an insecure §5a default the PMC rules dev-only (e.g., anonymous mode, public notebooks, no impersonation). | §5a |
BY-DESIGN: property-disclaimed | Concerns interpreter code execution or a property §9 disclaims. | §9 |
KNOWN-NON-FINDING | Matches a §11a pattern. | §11a |
MODEL-GAP | Cannot be routed above → revise the model. | §12 |
Grouped in waves; each states the proposed answer followed by the PMC answer (recorded by the Apache Zeppelin PMC, 2026-06-11). The core framing — RBAC (Shiro + notebook ACL + URL ACL + impersonation) is the trust boundary, not a sandbox, and a %sh from a run-capable user is the product working, not RCE — was confirmed by the PMC and is kept.
Wave 1 — scope & the insecure defaults (these reshape everything):
shiro.ini is a dev- convenience; the supported production posture requires Shiro or a trusted isolated network. So reports against an internet-exposed anonymous instance are OUT-OF-MODEL: non-default-build. Correct? (→ §5a, §3, §11a) → PMC: confirmed.notebook.public=true default. Proposed: public-by-default is intended convenience; operators needing isolation set it false. A “any user can read an empty-ACL note” report is by-design, not a bug. Correct? (→ §5a, §2) → PMC: confirmed — by-design.shared, and no binding mode is a security sandbox.Wave 2 — properties & enforcement: 5. URL ACL default. Are /interpreter, /credential, /configurations open to any authenticated role unless [urls] restricts them, or is there a built-in admin gate? (→ §5a, §8) → PMC: no built-in admin gate — it relies on shiro.ini [urls]. 6. Server-side ACL enforcement. Are notebook ACLs + role checks enforced on the server for every websocket/REST op (not just hidden in the UI)? Any ops that check only client-side? (→ §6, §8) → PMC: enforced server-side; there are no client-side-only checks. 7. Credential isolation. Does the credential store guarantee one user cannot read another user's injected credentials, including via a shared interpreter process? (→ §8, §9) → PMC: yes — per-user credentials are isolated.
Wave 3 — surfaces & limits: 8. First-class interpreters. Which interpreters/modules are supported for security purposes vs. community/unsupported (→ §2/§3 carve-out)? → PMC: all bundled interpreters are supported for security purposes (first-class). 9. Resource limits. Any limits on paragraph/result size, websocket rate, or concurrent interpreter launches? Where‘s the line between in-model pre-auth exhaustion and by-design expensive queries? (→ §6, §8) → PMC: VALID-HARDENING — please surface. No rate limit or concurrent-launch cap today; this is an area we would like the scan to flag and recommend improvements for. 10. Web-UI hardening. Does enabling http_security_headers give CSRF + XSS + clickjacking coverage, or are those partly the operator’s job? (→ §9) → PMC: VALID-HARDENING — please surface. No CSP, and CSRF is Origin-based only; concrete improvements from the scan are welcome. 11. Coexistence. This is a new THREAT_MODEL.md; SECURITY.md (currently a stub) should point at it as canonical, and the website security pages stay the operator how-to. Agree? (→ meta) → PMC: agreed.
Deferred for v0; a threat-model.yaml sidecar (entry points → trust, §5a defaults, §8 properties, §11a suppressions, §13 labels) can be generated once the prose is ratified.