← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-33589 · CWE-20 · Disclosed 2026-05-07

Lack of user input validation in the file upload functionality of Open Notebook v1

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a user who should only drop files in the mailbox learning how to open the filing cabinet instead

CVE-2026-33589 is an authenticated arbitrary file-read bug in Open Notebook's source upload flow. In affected versions <= 1.8.3, the POST /api/sources path accepts a user-controlled file_path; when type=upload, that path is handed to the extraction pipeline without proving it stays under the uploads directory. Result: a logged-in user can request files like /etc/passwd or /proc/self/environ, and Open Notebook stores the contents as a readable Source in the UI.

The vendor's MEDIUM 6.5 is basically fair in real environments. The upside pressure is obvious: confidentiality loss is real, the exploit is simple, and the advisory explicitly calls out access to environment variables and secrets. The downside pressure is stronger for enterprise prioritization: this requires an authenticated application user, only hits self-hosted Open Notebook deployments, and the blast radius is usually bounded to what the containerized app can read rather than instant host takeover.

"Authenticated file-read in a niche self-hosted app: serious per instance, but not a fleet-wide emergency."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Get a valid Open Notebook session

The attacker first needs ordinary application access to Open Notebook with permission to create or upload Sources. In practice this is a low bar for insider abuse, shared-lab deployments, or any instance where external collaborators get accounts, but it is still a hard gate compared with unauthenticated internet-facing bugs. Typical tooling is just a browser session or captured auth token reused in curl or Burp Suite.
Conditions required:
  • Target runs Open Notebook <= 1.8.3
  • Attacker has valid credentials or a stolen session
  • Attacker can reach the web UI or API
Where this breaks in practice:
  • SSO, MFA, VPN-only access, or private network placement can block opportunistic internet abuse
  • Many enterprise environments will not expose this niche self-hosted app broadly
  • If the attacker lacks source-upload rights, exploitation may stop here
Detection/coverage: Commodity vuln scanners are unlikely to prove exploitability without authenticated app context. IAM, SSO, reverse-proxy, and app audit logs are more useful than network IDS at this stage.
STEP 02

Abuse POST /api/sources with a crafted file_path

Using curl, Burp Suite, or Postman, the attacker sends type=upload and replaces the expected upload path with an arbitrary container path. Per the GitHub advisory, the vulnerable code path passes file_path directly into the extraction pipeline without validating that it resolves under the uploads directory.
Conditions required:
  • Authenticated access to the source creation endpoint
  • Knowledge of a readable target path inside the container
Where this breaks in practice:
  • Application-layer auth is mandatory
  • A reverse proxy or API gateway with tight request validation could break malformed requests, though most will not understand this semantic abuse
  • If the instance has been upgraded to 1.8.4, path resolution checks stop the exploit
Detection/coverage: Look for requests to /api/sources containing suspicious absolute paths or traversal-like patterns, though this variant often uses clean absolute paths such as /proc/self/environ rather than obvious ../ strings.
STEP 03

Read container-local files through the Sources UI

The vulnerable workflow ingests the chosen file and stores it as a Source, making the content readable back through normal application features. The advisory specifically calls out /proc/self/environ, which is a high-value target because it can expose runtime secrets, API keys, and encryption-related material available to the Open Notebook process.
Conditions required:
  • Requested file is readable by the app process
  • Source extraction succeeds for the chosen file
Where this breaks in practice:
  • The bug does not automatically cross the container boundary if sensitive host paths are not mounted in
  • Least-privilege container permissions and minimal mounted secrets reduce what can actually be stolen
  • Some target files may be unreadable or useless in a given deployment
Detection/coverage: App-side audit logs showing unexpected Source creation from non-upload paths are the best signal. EDR on the host may see unusual reads of /proc/self/environ or config files by the containerized process, but many teams will not have that telemetry tuned.
STEP 04

Turn leaked secrets into follow-on access

Impact escalates only if the exposed files contain credentials or tokens that matter elsewhere: model-provider API keys, database secrets, internal service URLs, or encryption keys. That can enable further data theft or limited lateral movement, but those are second-stage outcomes, not guaranteed by the flaw itself.
Conditions required:
  • Secrets of operational value are present in env vars, config files, or mounted volumes
  • Those secrets grant access to something beyond the current app session
Where this breaks in practice:
  • No integrity or availability impact is inherent in this CVE
  • Container isolation and secret scoping often keep the blast radius app-local
  • Many leaked values may be low-value or already rotated frequently
Detection/coverage: Secret-use monitoring, cloud audit logs, downstream API telemetry, and credential abuse detections matter more than HTTP signatures once this step starts.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo current evidence of active exploitation found in checked public sources, and it is not present in CISA KEV.
Proof-of-concept availabilityNo standalone public exploit repo was located during source review, but the vendor advisory gives enough detail to reproduce with curl or Burp: authenticated POST /api/sources, type=upload, attacker-controlled file_path.
EPSS0.00058 from your intel block, which is extremely low and consistent with a niche authenticated app bug rather than a mass-exploitation pattern.
KEV statusNot listed in the CISA Known Exploited Vulnerabilities Catalog as checked.
CVSS vector reality checkCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N says remote, low-complexity, low-privilege, confidentiality-only. That is directionally right: exploitation is easy *after login*, but there is no native write or code-exec primitive.
Affected versionsGitHub advisory lists Open Notebook <= 1.8.3 as affected; NVD maps the vulnerable range to versions up to, but excluding, 1.8.4.
Fixed versionPatched in 1.8.4, where file_path is validated to remain inside the uploads directory using path resolution checks.
Exposure / internet censusNo reliable product-specific Shodan/Censys/FOFA census signal was found in reviewed public sources. *Inference:* exposure is probably limited and hard to enumerate because Open Notebook is a self-hosted niche product typically deployed via Docker rather than a widely fingerprinted enterprise platform.
Disclosure timelineGitHub advisory was published on 2026-04-09; NVD published the CVE on 2026-05-07.
Researcher / reporterReported by CERT-EU Offensive Security Team per the GitHub advisory.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to MEDIUM (6.8/10)

The decisive factor is the attacker position requirement: this is an authenticated application-user bug in a niche self-hosted platform, which makes it a post-auth confidentiality issue rather than a broad initial-access event. The impact on a given instance can be ugly if secrets live in env vars or mounted files, but the reachable population and default blast radius are both materially narrower than the raw file-read mechanics suggest.

HIGH Technical exploitability and affected version range
MEDIUM Real-world exposure prevalence of Open Notebook in enterprise fleets
MEDIUM Practical blast radius beyond the container boundary

Why this verdict

  • Post-auth only: exploitation requires a valid Open Notebook user or stolen session, which means this is not an unauthenticated edge compromise and should be scored below internet-reachable pre-auth bugs.
  • Blast radius is usually container-bounded: the advisory shows arbitrary file read inside the Docker container, including /proc/self/environ; that is serious, but it is still limited by what the app process can read and what the operator mounted in.
  • Exploit chain is simple once inside: no user interaction, low complexity, and ordinary API tooling are enough to weaponize it, so this should not be dismissed as harmless just because it is 'only' confidentiality impact.
  • Population is narrow: Open Notebook is a popular open-source project but still a niche self-hosted application, not a ubiquitous enterprise control plane. That constrains fleet-level urgency even though individual exposed instances may hold sensitive research data and API secrets.
  • No active exploitation signal: no KEV listing and no public evidence of live campaigns means there is no threat-intel amplifier forcing an emergency re-prioritization.

Why not higher?

To get into HIGH, I would want either unauthenticated reachability, widespread exposure, or credible exploitation evidence. This CVE has none of those. It also does not natively provide integrity damage, denial of service, or code execution; any broader fallout depends on what secrets happen to be readable in that specific deployment.

Why not lower?

This is still an easy, repeatable arbitrary file-read against a live web application, not a theoretical hardening nit. The advisory explicitly names /proc/self/environ, source code, config, and secrets as readable targets, so a compromised or malicious low-privilege user can absolutely turn this into meaningful data exposure on real systems.

05 · Compensating Control

What to do — in priority order.

  1. Restrict Open Notebook to trusted users — Put the app behind SSO, MFA, VPN, or an internal reverse proxy and tighten who can create Sources. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but this is cheap risk reduction and worth doing now on externally reachable instances.
  2. Disable or gate source uploads where possible — If your deployment model allows it, temporarily remove upload capability for untrusted roles or collaborators until 1.8.4 is in place. There is no mitigation SLA for MEDIUM, but this is the most direct way to cut off the vulnerable code path without waiting for patch rollout.
  3. Minimize secrets visible to the container — Move long-lived credentials out of broad environment variables, avoid unnecessary mounted files, and scope tokens to least privilege. This does not fix the bug, but it lowers the payoff if someone reads /proc/self/environ or adjacent config during the remediation window.
  4. Audit recent Source creation activity — Review application and reverse-proxy logs for suspicious POST /api/sources requests and unexpected Source records that map to absolute paths or system files. Do this during normal remediation planning so you know whether you are dealing with a quiet patch job or an active investigation.
  5. Prepare secret rotation for exposed instances — If you suspect exploitation, be ready to rotate API keys, database credentials, and any encryption-related secrets reachable from the container. For MEDIUM there is no formal mitigation deadline, but incident response should not wait on the longer remediation window if evidence appears.
What doesn't work
  • A WAF alone will not reliably save you; the abusive input can be an ordinary absolute path like /proc/self/environ, not just obvious ../ traversal payloads.
  • Containerization by itself is not a fix; the bug is inside the app, and the container still contains env vars, source code, configs, and any mounted secrets.
  • Endpoint AV on the host is weak coverage here; this is authenticated misuse of normal application functionality, not a malware dropper.
06 · Verification

Crowdsourced verification payload.

Run this on the Docker host that runs Open Notebook, not from an auditor laptop. Invoke it as bash check_cve_2026_33589.sh for auto-detection or bash check_cve_2026_33589.sh <container_name_or_id> to target a specific container; it needs permission to talk to the Docker socket (root or a user in the docker group).

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_33589.sh
# Detects whether a running Open Notebook container is vulnerable to CVE-2026-33589.
# Exit codes:
#   0 = PATCHED
#   1 = VULNERABLE
#   2 = UNKNOWN / error

set -u

FIXED_VERSION="1.8.4"
TARGET="${1:-}"

version_le() {
  # returns 0 if $1 <= $2
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}

normalize_ver() {
  local v="$1"
  v="${v#v}"
  v="${v%%-*}"
  printf '%s' "$v"
}

find_container() {
  docker ps --format '{{.ID}} {{.Image}} {{.Names}}' | awk '
    BEGIN{IGNORECASE=1}
    /open[_-]?notebook/ {print $1; exit}
  '
}

extract_version_from_image() {
  local cid="$1"
  local image tag
  image="$(docker inspect --format '{{.Config.Image}}' "$cid" 2>/dev/null)" || return 1
  tag="${image##*:}"
  if [ "$tag" = "$image" ]; then
    return 1
  fi
  tag="$(normalize_ver "$tag")"
  if [[ "$tag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    printf '%s' "$tag"
    return 0
  fi
  return 1
}

extract_version_from_container() {
  local cid="$1"
  local v

  # Try Python package metadata / module attributes inside the container.
  v="$(docker exec "$cid" sh -lc '
python3 - <<"PY"
import sys
try:
    try:
        from importlib import metadata as m
    except Exception:
        import importlib_metadata as m  # type: ignore
    for name in ("open-notebook", "open_notebook"):
        try:
            print(m.version(name))
            sys.exit(0)
        except Exception:
            pass
except Exception:
    pass
for stmt in (
    "from open_notebook import __version__ as v; print(v)",
    "import open_notebook, sys; print(getattr(open_notebook, \"__version__\", \"\"))",
):
    try:
        exec(stmt, {})
        sys.exit(0)
    except Exception:
        pass
sys.exit(1)
PY
' 2>/dev/null | tr -d '\r' | tail -n1)"

  if [ -n "$v" ]; then
    v="$(normalize_ver "$v")"
    if [[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      printf '%s' "$v"
      return 0
    fi
  fi

  # Fallback: look for package.json or pyproject version hints.
  v="$(docker exec "$cid" sh -lc '
for f in /app/package.json /app/pyproject.toml /app/open_notebook/pyproject.toml; do
  [ -f "$f" ] || continue
  grep -Eom1 '"version"[[:space:]]*:[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"|version[[:space:]]*=[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"' "$f" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' && exit 0
done
exit 1
' 2>/dev/null | tr -d '\r' | tail -n1)"

  if [ -n "$v" ]; then
    printf '%s' "$v"
    return 0
  fi

  return 1
}

if ! command -v docker >/dev/null 2>&1; then
  echo "UNKNOWN: docker CLI not found"
  exit 2
fi

if [ -z "$TARGET" ]; then
  TARGET="$(find_container)"
fi

if [ -z "$TARGET" ]; then
  echo "UNKNOWN: no running Open Notebook container found"
  exit 2
fi

if ! docker inspect "$TARGET" >/dev/null 2>&1; then
  echo "UNKNOWN: container '$TARGET' not found"
  exit 2
fi

VERSION=""
VERSION="$(extract_version_from_container "$TARGET" 2>/dev/null)" || true
if [ -z "$VERSION" ]; then
  VERSION="$(extract_version_from_image "$TARGET" 2>/dev/null)" || true
fi

if [ -z "$VERSION" ]; then
  echo "UNKNOWN: could not determine Open Notebook version for container '$TARGET'"
  exit 2
fi

if version_le "$VERSION" "1.8.3"; then
  echo "VULNERABLE: Open Notebook version $VERSION detected in container '$TARGET' (fixed in $FIXED_VERSION)"
  exit 1
fi

if version_le "$FIXED_VERSION" "$VERSION"; then
  echo "PATCHED: Open Notebook version $VERSION detected in container '$TARGET'"
  exit 0
fi

echo "UNKNOWN: determined version '$VERSION' but comparison failed"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: identify every Open Notebook deployment, confirm which ones are externally reachable, and verify whether any instance is still on <= 1.8.3. This is a MEDIUM in noisgate terms, so there is noisgate mitigation SLA — no mitigation SLA, go straight to the 365-day remediation window — but for any internet-reachable or multi-user deployment you should still tighten access and review logs now while scheduling upgrade to 1.8.4 inside the noisgate remediation SLA of <= 365 days; if you find suspicious Source creation or evidence of secret exposure, treat that as an incident and accelerate patching plus credential rotation immediately.

Sources

  1. NVD entry for CVE-2026-33589
  2. GitHub advisory GHSA-842v-h4cj-r646
  3. Open Notebook GitHub repository
  4. Open Notebook project website
  5. CISA Known Exploited Vulnerabilities Catalog
  6. FIRST EPSS overview
  7. FIRST EPSS daily data and stats
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.