# SCAN: OpenUI date: 2026-02-14 | program: OpenUI | repo: https://github.com/wandb/openui | bounty: $0-$1500 ## summary raw_findings: 35 | real: 2 | high_conf: 1 | med_conf: 1 | low_conf: 0 | false_pos: 33 scan_method: semgrep + trufflehog + manual_review version: 0.5.0 | commit: f9d8f0e30e1efe2a21bbefffba33bcf6b4e12dc7 ## key finding ### HIGH — Predictable LiteLLM master key due to incorrect string interpolation In `backend/openui/config.py`, when `LITELLM_MASTER_KEY` is not set, OpenUI sets it to the literal string `sk-{SESSION_KEY}` (missing f-string interpolation). OpenUI can start a LiteLLM proxy subprocess (`litellm --port 4000`) in `backend/openui/__main__.py` when run with `--litellm`. If the LiteLLM proxy is reachable in the deployment environment (e.g., exposed by operators, reachable within a cluster/network, or reachable from sibling containers), an attacker can authenticate using a known/default master key value and gain unauthorized access to LiteLLM proxy capabilities. Occurrence(s): - `backend/openui/config.py` — sets `LITELLM_MASTER_KEY` to a constant string - `backend/openui/__main__.py` — spawns `litellm ... --port 4000` Verdict: reportable, but confirm deployment reachability assumptions before submitting (external exposure vs internal-only). ### MED — Unauthenticated share creation allows arbitrary S3 object writes (storage abuse / content poisoning) `POST /v1/share/{id}` does not require login/session and writes attacker-controlled JSON payloads to the configured S3 bucket key `{id}.json`. `GET /v1/share/{id}` returns the object without auth. This enables: - arbitrary content injection into publicly retrievable shared artifacts (by choosing `id` values) - unbounded storage/cost abuse (upload large `html`/payloads repeatedly) Occurrence(s): - `backend/openui/server.py` — `create_share()` uses `storage.upload(f\"{id}.json\", ...)` with no auth checks - `backend/openui/util/storage.py` — direct S3 `put_object` / `get_object` Verdict: likely reportable as improper access control (depends on intended sharing model; if sharing is intended to be read-only and user-authored, this is a bug). ## trufflehog notes - 5 unverified hits (SentryToken/CircleCI patterns) in `backend/uv.lock` / `backend/openui/eval/svg_annotator.html`. Likely false positives; verify before treating as leaks. ## skipped / false positives (high level) - semgrep `eval-detected` flagged functions named `eval(...)` (not Python `eval()` usage) - semgrep flagged `session_store.write(...)` as request data write; it writes to SQLite via Peewee, not filesystem - postMessage `targetOrigin='*'` findings are likely acceptable given explicit `event.origin` validation on the receiver side, but keep for manual review