CVE-2025-47942 Overview
CVE-2025-47942 is a missing authorization vulnerability [CWE-862] in the Open edX Platform (edxapp), a widely deployed learning management system. Before commit 6740e75c0fdc7ba095baf88e9f5e4f3e15cfd8ba, the platform did not restrict downloads of the python_lib.zip course asset. This file frequently contains custom Python grading code and answers to course problems. Any course using custom Python-graded problem blocks is potentially affected.
A temporary nginx-based mitigation existed in the deprecated openedx/configuration repository since 2016, but no equivalent protection was carried into Tutor, the current recommended deployment tool. Most production deployments likely lack protection against this asset being downloaded by unauthenticated users.
Critical Impact
Unauthenticated attackers can download python_lib.zip from vulnerable Open edX courses, exposing custom grading logic and answer keys used for Python-graded problems.
Affected Products
- Open edX Platform (edx-platform) prior to commit 6740e75c0fdc7ba095baf88e9f5e4f3e15cfd8ba
- Tutor-based Open edX deployments without custom access controls
- Open edX courses using custom Python-graded problem blocks
Discovery Timeline
- 2025-05-21 - CVE-2025-47942 published to NVD
- 2026-06-17 - Last updated in NVD database
Technical Details for CVE-2025-47942
Vulnerability Analysis
The vulnerability stems from missing authorization on the content server responsible for serving course static assets in edxapp. The python_lib.zip archive is a special course asset used by the Python-graded problem sandbox. Course authors package custom grading logic, helper libraries, and reference answers inside the archive so the sandbox can import them at grade time.
The content server treated python_lib.zip like any other course asset and served it to any requester who knew or guessed its URL. No authentication check, course-team check, or staff role check gated the download. Attackers who obtained the file could inspect grading code, extract answers to problems, and bypass or subvert automated grading in Python-graded exercises.
The patched code in openedx/core/djangoapps/contentserver/views.py introduces the has_studio_read_access helper and a course_code_library_asset_name utility to identify the sensitive asset and restrict access to the course team and site staff or superusers.
Root Cause
The root cause is an authorization gap. The content server enforced no role check for the python_lib.zip asset name, and the historical nginx rule in the deprecated openedx/configuration repository was never migrated to Tutor. Deployments upgrading through Tutor inherited no equivalent protection.
Attack Vector
Exploitation requires only network access to the Open edX site. An unauthenticated attacker requests the python_lib.zip URL under a target course's asset path. The server returns the archive, disclosing its contents.
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locator import AssetLocator
+from common.djangoapps.student.auth import has_studio_read_access
from common.djangoapps.student.models import CourseEnrollment
from openedx.core.djangoapps.header_control import force_header_for_response
+from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
from xmodule.assetstore.assetmgr import AssetManager
from xmodule.contentstore.content import XASSET_LOCATION_TAG, StaticContent
from xmodule.exceptions import NotFoundError
from xmodule.modulestore import InvalidLocationError
from xmodule.modulestore.exceptions import ItemNotFoundError
+from xmodule.util.sandboxing import course_code_library_asset_name
# Source: https://github.com/openedx/edx-platform/commit/6740e75c0fdc7ba095baf88e9f5e4f3e15cfd8ba
# The patch adds has_studio_read_access and course_code_library_asset_name
# imports used to gate python_lib.zip downloads.
Detection Methods for CVE-2025-47942
Indicators of Compromise
- HTTP GET requests to URLs ending in /python_lib.zip under any course asset path from unauthenticated clients or unenrolled users.
- Repeated 200-status responses for python_lib.zip from source IPs that do not belong to course staff.
- Anomalous download volume of static course assets outside normal instructor or CI activity.
Detection Strategies
- Parse nginx and application access logs for requests matching */python_lib.zip and correlate with authenticated session identity.
- Alert when the response size or content-type for python_lib.zip indicates a successful archive download to a non-staff principal.
- Retrospectively hunt across historical web logs to identify prior enumeration of the asset URL.
Monitoring Recommendations
- Forward Open edX web tier and application logs to a centralized analytics platform and retain them long enough to investigate pre-patch exposure.
- Baseline expected downloaders of python_lib.zip (course team, CI systems) and flag deviations.
- Monitor Studio audit events for unusual access patterns to Python-graded problem blocks.
How to Mitigate CVE-2025-47942
Immediate Actions Required
- Upgrade edx-platform to a release that includes commit 6740e75c0fdc7ba095baf88e9f5e4f3e15cfd8ba or later.
- Audit all courses that use custom Python-graded problem blocks and rotate any answer keys or secrets that may have been exposed in python_lib.zip.
- Review web access logs for prior downloads of python_lib.zip by unauthorized principals.
Patch Information
The fix is committed in openedx/edx-platform commit 6740e75c0fdc7ba095baf88e9f5e4f3e15cfd8ba, which restricts python_lib.zip downloads to the course team and to site staff or superusers. See the GitHub Security Advisory GHSA-x5cm-2hpq-pw57 and the patch commit for the authoritative fix.
Workarounds
- Apply an nginx or reverse-proxy rule that blocks or restricts requests for python_lib.zip under course asset paths, modeled on the historical edx/configuration nginx template.
- For Tutor deployments, add a custom Caddy or nginx snippet through a Tutor plugin to deny external requests to the asset until upgrade is possible.
- Restrict site access to authenticated users at the edge where feasible while planning the upgrade.
# Example nginx snippet to deny external python_lib.zip downloads
location ~* /asset-v1:[^/]+/python_lib\.zip$ {
# Allow only internal or staff networks; deny everything else
allow 10.0.0.0/8;
deny all;
return 403;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

