This is a shared office whiteboard where any logged-in employee can quietly rewrite someone else's notes
CVE-2026-28788 is an IDOR/BOLA-style authorization failure in Open WebUI's POST /api/v1/retrieval/process/files/batch endpoint. In versions <=0.8.5, any authenticated user can overwrite file content by UUID because the route accepts a verified user but does not verify file ownership before updating the record. The vendor advisory says the attacker can first enumerate valid file UUIDs from GET /api/v1/knowledge/{id}/files when they have read access to a shared knowledge base, then replace the file contents that downstream RAG uses.
The vendor's HIGH 7.1 is technically defensible in a lab because exploitation is simple once prerequisites are met, but it overstates enterprise urgency in the real world. This is not unauthenticated internet-edge compromise; it is *post-auth, shared-resource abuse* with impact concentrated on knowledge-base integrity and downstream model responses, not host takeover or tenant-wide compromise. Low EPSS, no KEV listing, and a requirement for authenticated access plus visibility into a shared knowledge base all push this down to MEDIUM.
4 steps from start to impact.
Gain a normal Open WebUI session
get_verified_user check, meaning any logged-in user can reach it. Practical weaponization usually starts with curl, Burp Suite, or an existing session cookie.- Authenticated Open WebUI user session
- Target deployment is running
<=0.8.5 - Multi-user mode is enabled
- Single-user deployments with
WEBUI_AUTH=Falsechange the trust model and may not expose this exact multi-user abuse path - Many enterprise deployments keep Open WebUI behind VPN, SSO, zero-trust proxy, or internal-only access
- Open signup is not default after the first admin account is created
Enumerate file UUIDs from a shared knowledge base
GET /api/v1/knowledge/{id}/files discloses valid file UUIDs for documents in that knowledge base, which supplies the object identifiers needed for the overwrite. Tooling is trivial: browser dev tools, curl, or Burp Repeater.- Attacker can see at least one shared knowledge base
- Knowledge base contains documents owned by another user or team
- Attacker can call
GET /api/v1/knowledge/{id}/files
- If knowledge bases are private per user or tightly segmented, there may be no cross-user targets
- No UUID discovery means no exploit path; this is not blind internet exploitation
- Smaller deployments may not use shared RAG stores at all
Overwrite the target file through process_files_batch
POST /api/v1/retrieval/process/files/batch with the victim file UUID and attacker-controlled replacement content. The vulnerable path updates the file by ID without confirming ownership, so a standard user escalates from read to write over shared RAG content. curl, Burp Suite, or a short Python script is enough; no exploit kit is needed.- Valid file UUIDs
- Authenticated user token
- Endpoint reachable and unpatched
- Reverse proxies, WAFs, and auth gateways may log the request, though they usually will not block it because it is application-legitimate traffic
- If the deployment upgrades to
>=0.8.6, the path is closed - Blast radius is limited to files the attacker can identify in shared knowledge spaces
Poison downstream RAG answers
- The overwritten file is actually used by RAG retrieval
- Other users query topics that pull that file into context
- The knowledge base remains trusted by operators
- If the poisoned file is rarely retrieved, real impact may stay low
- Human review, citation checking, or source validation can expose manipulated content
- This does not itself grant OS-level code execution or admin control
The supporting signals.
| In-the-wild status | No confirmed active exploitation found in CISA KEV or the sources reviewed. OpenCVE shows KEV: No and CISA ADP SSVC marks exploitation as poc, not active campaign evidence. |
|---|---|
| Proof-of-concept availability | Yes, effectively yes. The public GHSA advisory includes enough endpoint-level detail and code-path explanation to build a working request with curl/Burp in minutes; OpenCVE also records SSVC Exploitation: poc. |
| EPSS | 0.00016 per OpenCVE, which is *very low* and aligns with a niche, post-auth abuse case rather than mass opportunistic exploitation. |
| KEV status | Not KEV-listed as of the reviewed sources. That matters because KEV absence removes the strongest current exploit-pressure amplifier. |
| CVSS vector meaning | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L = network reachable, easy to exploit, but requires low privileges and mainly damages integrity rather than confidentiality or full availability. |
| Affected versions | <=0.8.5 per GHSA, NVD, and OSV. OSV models the range as all prior commits fixed at commit 9c9a18d... / version 0.8.6. |
| Fixed version | Upgrade to 0.8.6 or later. 0.8.6" target="_blank" rel="noopener">Release v0.8.6 was published on 2026-03-01, before public advisory publication later in March. |
| Exposure population | Internet exposure exists, but it is highly deployment-specific. Open WebUI docs show straightforward port publishing (-p 3000:8080) and public HTTPS patterns, while the hardening guide explicitly recommends VPN/zero-trust/reverse-proxy protection; third-party reporting in July 2025 cited 17,000+ Shodan-listed instances, but that number is not version-specific and should be treated as population context, not vuln-specific exposure. |
| Disclosure timeline | There are multiple close dates: the GHSA was published on 2026-03-26, MITRE/OpenCVE shows CVE publication on 2026-03-26 UTC, and NVD enrichment followed on 2026-03-27. If your internal tracking says 2026-03-27, that is plausibly the NVD/public-enrichment date rather than the first public CVE record. |
| Reporter / researcher | The GitHub advisory credits Inar1Dev as the reporter. |
noisgate verdict.
The decisive factor is that this bug requires authenticated access plus visibility into a shared knowledge base, which makes it a post-initial-access integrity abuse path, not an internet-edge compromise event. The impact is real, but it is mostly limited to poisoning shared RAG content and model output rather than delivering host takeover, tenant escape, or broad unauthenticated compromise.
Why this verdict
- Down from vendor HIGH because it needs post-auth access: the attacker must already hold a valid Open WebUI session, which implies prior compromise, insider access, or a weak identity boundary.
- Further down because it needs shared-knowledge visibility: the exploit chain depends on read access to a shared knowledge base so the attacker can enumerate victim file UUIDs. Private or tightly segmented knowledge bases sharply reduce reachable targets.
- Impact is mostly integrity poisoning, not platform takeover: the bug rewrites RAG content and can manipulate model answers, but the published record does not show direct OS execution, database dump, or admin privilege escalation.
- No current exploit-pressure amplifiers: EPSS is
0.00016, KEV isNo, and the reviewed sources do not show active exploitation campaigns. - Still not LOW: exploitation is straightforward once prerequisites are met, uses ordinary API calls, and can silently corrupt business decision support if Open WebUI is used for shared internal knowledge retrieval.
Why not higher?
This is not unauthenticated remote compromise, not wormable, and not a direct route to system-level code execution from the published advisory. The attack population shrinks at each prerequisite: authenticated user, shared knowledge base access, target file UUID discovery, and actual downstream RAG dependence on the poisoned file.
Why not lower?
Once an attacker has a normal user account and shared knowledge-base visibility, exploitation is low-friction and the integrity impact is meaningful. In organizations using Open WebUI for internal policy, engineering, or support knowledge, poisoned RAG content can create materially bad answers at scale, so dismissing it as mere hygiene would be too relaxed.
What to do — in priority order.
- Put Open WebUI behind a strong identity boundary — Require VPN, zero-trust proxy, or SSO-backed reverse proxy in front of Open WebUI and deploy this within the noisgate remediation window only after patching? No—because this is a
MEDIUM, there is no mitigation SLA; use it as a priority hardening step while you work toward remediation within 365 days. This directly attacks the biggest amplifier: authenticated access by the wrong user. - Reduce shared knowledge-base exposure — Limit broad read access to shared knowledge bases, especially cross-team repositories, and review who can list files in each space. Do this during the
MEDIUMremediation cycle, because the exploit requires discoverable shared targets more than it requires exotic tooling. - Audit file ownership and recent content changes — Review file update history, file UUID access patterns, and changes made by low-privilege users to documents they do not own. Run this immediately as a detection control and continue until all instances are upgraded within the 365-day remediation window.
- Pin and inventory Open WebUI versions — Stop running floating
:mainor:devtags in production where possible and map each deployment to an exact image or package version. For thisMEDIUM, there is no mitigation SLA — go straight to the 365-day remediation window, but version certainty is what lets you close the issue confidently.
- A generic network firewall alone does not solve this if legitimate users can still reach the application, because the exploit rides normal authenticated API traffic.
- MFA by itself is not enough once a valid low-privilege session exists; this is an authorization flaw after login, not an authentication bypass.
- Relying on a WAF to block malicious payloads is weak here because the request shape is application-native and the core problem is missing ownership checks.
- Disabling internet exposure without reviewing internal access is incomplete; an internal user or attacker with foothold access can still abuse shared knowledge bases.
Crowdsourced verification payload.
Run this on the target Linux host that runs Open WebUI, ideally with permission to query Docker/Podman or read the local Python environment. Save it as check-openwebui-cve-2026-28788.sh, then run bash check-openwebui-cve-2026-28788.sh or bash check-openwebui-cve-2026-28788.sh /opt/open-webui-venv/bin/python; root is not required, but access to the container runtime socket may be.
#!/usr/bin/env bash
# Check for CVE-2026-28788 exposure in Open WebUI
# Outputs: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
set -u
TARGET_FIXED="0.8.6"
PYTHON_BIN="${1:-python3}"
log() { printf '%s\n' "$*"; }
verlte() {
# returns 0 if $1 <= $2 using sort -V
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}
verlt() {
[ "$1" != "$2" ] && verlte "$1" "$2"
}
normalize_tag() {
local v="$1"
v="${v#v}"
v="${v%%-*}"
printf '%s' "$v"
}
check_version() {
local source="$1"
local version_raw="$2"
local version
version="$(normalize_tag "$version_raw")"
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
log "UNKNOWN - Could not parse semantic version from $source: $version_raw"
return 2
fi
if verlt "$version" "$TARGET_FIXED"; then
log "VULNERABLE - $source reports Open WebUI version $version (< $TARGET_FIXED)"
return 1
else
log "PATCHED - $source reports Open WebUI version $version (>= $TARGET_FIXED)"
return 0
fi
}
# 1) Docker container image tags
if command -v docker >/dev/null 2>&1; then
while IFS= read -r line; do
cid="${line%% *}"
image="${line#* }"
if [[ "$image" == *"open-webui"* ]]; then
tag="${image##*:}"
check_version "Docker image $image" "$tag"
exit $?
fi
done < <(docker ps --format '{{.ID}} {{.Image}}' 2>/dev/null)
fi
# 2) Podman container image tags
if command -v podman >/dev/null 2>&1; then
while IFS= read -r line; do
cid="${line%% *}"
image="${line#* }"
if [[ "$image" == *"open-webui"* ]]; then
tag="${image##*:}"
check_version "Podman image $image" "$tag"
exit $?
fi
done < <(podman ps --format '{{.ID}} {{.Image}}' 2>/dev/null)
fi
# 3) Python package metadata from provided or default interpreter
if command -v "$PYTHON_BIN" >/dev/null 2>&1; then
PKG_VERSION="$($PYTHON_BIN - <<'PY' 2>/dev/null
import sys
mods = []
try:
try:
from importlib.metadata import version, PackageNotFoundError
except Exception:
from importlib_metadata import version, PackageNotFoundError
for name in ("open-webui", "open_webui"):
try:
print(version(name))
raise SystemExit(0)
except PackageNotFoundError:
pass
except Exception:
pass
raise SystemExit(1)
PY
)"
if [ -n "${PKG_VERSION:-}" ]; then
check_version "Python package" "$PKG_VERSION"
exit $?
fi
fi
# 4) Local filesystem hints for pinned compose/container files
for f in docker-compose.yml docker-compose.yaml compose.yml compose.yaml; do
if [ -f "$f" ] && grep -qi 'open-webui' "$f"; then
tag="$(grep -i 'open-webui' "$f" | sed -n 's/.*open-webui:\([^[:space:]]*\).*/\1/p' | head -n1)"
if [ -n "$tag" ]; then
check_version "Compose file $f" "$tag"
exit $?
fi
fi
done
log "UNKNOWN - Could not determine an installed Open WebUI version from Docker, Podman, Python metadata, or local compose files"
exit 2
If you remember one thing.
<=0.8.5 from >=0.8.6, then verify whether those vulnerable instances are multi-user and use shared knowledge bases. Because this is a MEDIUM, there is no noisgate mitigation SLA — go straight to the 365-day remediation window; use that noisgate remediation SLA to upgrade all vulnerable nodes to 0.8.6+, but prioritize earlier patching for any internet-exposed or broadly shared internal deployments where poisoned RAG content could mislead users across teams.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.