CVE-2026-85272 Overview
CVE-2026-85272 is a path traversal vulnerability [CWE-22] in the Open edX Platform, which powers authoring and delivery of online learning at scale. The flaw resides in openedx/core/lib/extract_archive.py, where the _is_bad_path helper validates safe_extractall targets using string startswith comparisons instead of proper path component comparison. A course author or staff user with course import permission can submit a crafted .tar.gz archive through the import_olx flow initiated by cms.djangoapps.contentstore.views.import_export.import_handler. Archive members can escape into a sibling course staging directory whose name shares the attacker's base64 directory prefix. The issue affects releases from Aspen.1 until Ulmo and Verawood.1.
Critical Impact
An authenticated course author can corrupt files in sibling course staging directories on the same tenant, resulting in limited cross-tenant file corruption. The advisory does not establish arbitrary filesystem writes, file reads, or direct code execution.
Affected Products
- Open edX Platform releases from Aspen.1 up to (but not including) Ulmo
- Open edX Platform Verawood release prior to Verawood.1
- Open edX Studio (CMS) instances exposing the import_olx course import flow
Discovery Timeline
- 2026-09-18 - CVE-2026-85272 published to NVD
- 2026-09-24 - Last updated in NVD database
Technical Details for CVE-2026-85272
Vulnerability Analysis
The vulnerability affects the tar archive extraction routine used during Open edX course import. Open edX accepts an Open Learning XML (OLX) course package uploaded by staff users. During extraction, safe_extractall iterates over TarInfo members and validates each destination path with _is_bad_path. The check compares the resolved absolute path of the extraction target with the resolved absolute path of the destination base directory using string prefix matching.
String prefix matching does not treat filesystem components atomically. If the base directory is /edx/var/edxapp/course_import/course_abc123, then a resolved path such as /edx/var/edxapp/course_import/course_abc123_evil/payload satisfies startswith but resides in a sibling directory. An attacker crafting an archive with member paths that traverse to sibling staging directories bypasses the guard.
Zip archives are not practically exploitable because Python's ZipFile.extractall strips parent traversal segments. The attack is limited to tar-family archives (.tar, .tar.gz).
Root Cause
The root cause is unsafe string comparison for path containment. Using resolved_target.startswith(resolved_base) treats path strings as opaque byte sequences and allows a sibling directory whose name begins with the same characters to pass validation. The fix replaces the prefix check with os.path.commonpath, which compares full path components and correctly rejects sibling directories.
Attack Vector
Exploitation requires an authenticated Studio user with course import privileges. The attacker enumerates or predicts the base64-derived staging directory naming pattern used by the course import handler, then crafts a .tar.gz whose entries resolve to a sibling staging directory belonging to another course or tenant. Uploading the archive through import_handler triggers extraction and writes attacker-controlled bytes into the sibling location, corrupting or overwriting files that belong to another course.
# Patch: openedx/core/lib/extract_archive.py
# Source: https://github.com/openedx/openedx-platform/commit/8422334e2063015a28b6460a34aa4bb4d8ae1ca8
import logging
-from os.path import abspath, dirname, realpath
+from os.path import abspath, commonpath, dirname, realpath
from os.path import join as joinpath
from tarfile import TarFile, TarInfo
from typing import List, Union # noqa: UP035
The patch imports commonpath and replaces the startswith comparison with a component-aware containment check, ensuring an extraction target must share a full path prefix (component-by-component) with the destination base directory.
Detection Methods for CVE-2026-85272
Indicators of Compromise
- Course import audit log entries in cms.djangoapps.contentstore referencing .tar.gz uploads followed by writes to staging directories the requesting user does not own.
- Filesystem modification timestamps in course_import staging directories that do not correlate to the import initiated by the directory's owning user.
- TarInfo member names in uploaded archives containing sibling-directory prefixes rather than the expected relative paths inside the course root.
Detection Strategies
- Inspect archived tar members prior to extraction and reject any member whose resolved absolute path is not contained (by os.path.commonpath) within the intended base directory.
- Enable filesystem integrity monitoring on the Open edX course import staging root and alert on writes crossing per-course directory boundaries.
- Correlate Studio user identity from import_handler requests with the write targets recorded during extraction to identify cross-tenant writes.
Monitoring Recommendations
- Log every import_olx invocation with the requesting user, target course key, and the list of extracted paths.
- Alert on any tar member name containing .., absolute paths, or naming patterns that resemble other course staging directory identifiers.
- Track anomalies in course content modification rates that may indicate unauthorized overwrites of a neighboring course.
How to Mitigate CVE-2026-85272
Immediate Actions Required
- Upgrade Open edX Platform to ulmo.4 or verawood.1, which contain the commonpath fix in openedx/core/lib/extract_archive.py.
- Restrict the course.import permission to a minimal set of trusted staff users until upgrades are deployed.
- Audit recent course import activity for unexpected writes into staging directories belonging to other courses.
Patch Information
The fix is delivered in the Ulmo and Verawood.1 releases. See the GitHub Security Advisory GHSA-6cmm-8875-5pcw, the Ulmo.4 release, and the Verawood.1 release. The corrective commits are 8422334, 97de0586, and e552907f.
Workarounds
- Disable tar-family archive uploads in the course import flow and accept only .zip packages, which are not practically affected because ZipFile.extractall strips parent traversal segments.
- Isolate each course staging directory on a distinct filesystem mount or per-user chroot so a sibling-prefix escape cannot land inside another course's data.
- Apply a temporary patch that replaces the _is_bad_path prefix check with a commonpath-based containment check while planning the full upgrade.
# Verify running Open edX version and plan upgrade to a patched release
tutor local run cms python -c "import openedx; print(openedx.__version__)"
# Upgrade to a patched release
git fetch --tags
git checkout release/verawood.1 # or release/ulmo.4
tutor images build openedx
tutor local start -d
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

