CVE-2026-25645
Medium · 4.4CVSS
4.4
EPSS
0.2%
Published
Mar 25, 2026
CISA due date
—
Cloudanix analysis
Some applications using an older Python web library could be tricked by a local user into reading a fake temporary file instead of the real one.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- High
- Impact
- Data Tampering
- Component
- Library
- Class
- Race Condition
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
This is a local file-substitution race condition in Python Requests before 2.33.0, limited to applications that directly call requests.utils.extract_zipped_paths(). The vulnerable helper extracts files from ZIP archives into the system temporary directory using a predictable destination path and reuses an existing file without validating that it was created from the expected archive content. A local attacker who can write to the same temporary directory can pre-create the expected extracted file so that the application later loads attacker-controlled content instead of the legitimate ZIP member. Standard HTTP client usage of Requests is not affected.
Why it matters to the business
Business risk is generally limited because exploitation requires local access, write permission to the temporary directory, and an application-specific code path that directly uses the vulnerable utility. Where affected, the impact can be significant: applications may process or trust attacker-supplied local content, potentially causing data corruption, incorrect business logic decisions, poisoned configuration or resource files, or further compromise depending on how the extracted file is used. The low EPSS score and absence from CISA KEV indicate no current evidence of broad exploitation, but organizations with Python applications that use this helper should still remediate during normal patch cycles.
How an attack unfolds
An attacker first obtains low-privileged local access on a system running a Python application that directly invokes requests.utils.extract_zipped_paths(). The attacker determines or predicts the temporary-file path that Requests will use when extracting a file from a ZIP archive. Before the application performs extraction, the attacker creates a malicious file at that predictable path in a shared temporary directory such as /tmp. When the application later calls the vulnerable helper, Requests sees the file already present and reuses it rather than validating or replacing it with the ZIP member. The application then consumes the attacker-controlled file as if it came from the trusted archive. The practical result depends on the application: the attacker may influence file parsing, load malicious data, poison caches, or alter application behavior.
How to fix it
Upgrade Python Requests to version 2.33.0 or later, where extraction uses a non-deterministic location. Because standard Requests HTTP usage is not affected, prioritize systems and applications that directly call requests.utils.extract_zipped_paths(). If immediate upgrade is not possible, set TMPDIR to a directory that is not world-writable and is writable only by the application user, and ensure equivalent controls are applied for other platform-specific temporary-directory environment variables where relevant. Review application code for direct use of extract_zipped_paths() and replace it with safer extraction logic where possible, including unique temporary directories, secure file creation, ownership validation, and cleanup.
How to confirm the fix worked
Confirm installed Requests versions by inspecting package inventories, virtual environments, containers, build manifests, and lockfiles; affected deployments use requests versions earlier than 2.33.0. Confirm whether the application directly imports or calls requests.utils.extract_zipped_paths(); systems that do not call this utility are not affected by the described issue. Validate remediation by verifying Requests 2.33.0 or later is installed in the runtime actually used by the application. For mitigated systems, confirm TMPDIR points to a restricted directory owned by the application user and not writable by other local users. A practical exposure test is to run the affected application path in a non-production test environment while monitoring whether extracted ZIP members are written to predictable names in a shared temporary directory or whether pre-existing files are reused.
Typical attack path
- Identify a Python application that uses Requests before version 2.33.0 and directly calls requests.utils.extract_zipped_paths().
- Gain local low-privileged access or another ability to write into the same system temporary directory used by the application.
- Predict the filename or path that the vulnerable helper will use for ZIP extraction.
- Pre-create a malicious file at that path before the target application performs extraction.
- Wait for or trigger the application code path that calls extract_zipped_paths().
- Cause the application to read or process the attacker-controlled file instead of the intended ZIP archive member.
- Leverage the application-specific handling of that file to alter behavior, corrupt data, or support further compromise.
How to detect it
There are no widely reported public exploitation patterns or known threat actors associated with this vulnerability, and it is not listed in CISA KEV. Detection should focus on exposure and local tampering evidence. Review application dependency inventories, SBOMs, virtual environments, and container images for Requests versions before 2.33.0. Search application source and deployed packages for direct use of requests.utils.extract_zipped_paths(). For possible exploitation, examine operating system audit logs, EDR file telemetry, and application logs for files created in shared temporary directories shortly before the affected application reads or extracts ZIP content. Look for temporary files owned by a different user than the application process, unexpected persistence of extracted files, permission anomalies, or repeated creation of the same predictable temporary path. On Linux, auditd or EDR events for open, creat, chmod, chown, and rename operations under /tmp, /var/tmp, or the configured TMPDIR can help reconstruct whether an unprivileged user pre-positioned files consumed by the application.
- requests.utils.extract_zipped_paths
- extract_zipped_paths(
- from requests.utils import extract_zipped_paths
- /tmp
- /var/tmp
- TMPDIR
What your security team should do
- Inventory Python applications and containers using the requests package and identify versions earlier than 2.33.0.
- Search source code and dependency usage for direct calls to requests.utils.extract_zipped_paths(); prioritize remediation only where that utility is used.
- Upgrade affected environments to Requests 2.33.0 or later and rebuild/redeploy application images so the fixed library is present at runtime.
- Where upgrade is delayed, set TMPDIR to an application-private directory with restrictive permissions and verify it is not shared or world-writable.
- Review local-user threat models for multi-user servers, shared build systems, CI runners, batch workers, and application hosts where untrusted users or jobs can write to shared temporary directories.
- Add code-review checks to discourage predictable temporary-file use and unsafe ZIP extraction patterns.
- Monitor for suspicious pre-created files or ownership mismatches in temporary directories used by affected applications, especially around application execution times.
The record
Requests is a HTTP library. Prior to version 2.33.0, the `requests.utils.extract_zipped_paths()` utility function uses a predictable filename when extracting files from zip archives into the system temporary directory. If the target file already exists, it is reused without validation. A local attacker with write access to the temp directory could pre-create a malicious file that would be loaded in place of the legitimate one. Standard usage of the Requests library is not affected by this vulnerability. Only applications that call `extract_zipped_paths()` directly are impacted. Starting in version 2.33.0, the library extracts files to a non-deterministic location. If developers are unable to upgrade, they can set `TMPDIR` in their environment to a directory with restricted write access.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| Chainguard | airflow-3 | 0 | 3.1.8-r10 |
| Chainguard | airflow-core-2 | 0 | 2.11.2-r3 |
| Chainguard | airflow-core-3 | 0 | 3.1.8-r3 |
| Chainguard | apache-beam-python-3.11-sdk | 0 | 2.71.0-r8 |
| Chainguard | apache-beam-python-3.12-sdk | 0 | 2.71.0-r2 |
| Chainguard | apache-beam-python-3.13-sdk | 0 | 2.71.0-r2 |
| Chainguard | awx | 0 | 24.6.1-r33 |
| Chainguard | az | 0 | 2.84.0-r4 |
| Chainguard | barman-cloudnative-pg | 0 | 3.18.0-r1 |
| Chainguard | checkov | 0 | 3.2.511-r0 |
| Chainguard | confluent-docker-utils | 0 | 0.0.169-r1 |
| Chainguard | dask-kubernetes | 0 | 2026.3.0-r2 |
| Chainguard | datahub-ingestion | 0 | 1.5.0.1-r0 |
| Chainguard | datahub-ingestion-fips | 0 | 1.5.0.1-r0 |
| Chainguard | gitlab-toolbox-ce-18.9 | 0 | 18.9.3-r1 |
| Chainguard | gitlab-toolbox-ce-fips-18.9 | 0 | 18.9.3-r1 |
| Chainguard | jupyter-base-notebook | 0 | 7.5.5-r1 |
| Chainguard | k8s-sidecar | 0 | 2.5.1-r3 |
| Chainguard | keep-api | 0 | 0.51.0-r2 |
| Chainguard | keep-api-fips | 0 | 0.51.0-r2 |
| Chainguard | kserve-storage-controller | 0 | 0.16.0-r24 |
| Chainguard | kubeflow-jupyter-web-app | 0 | 1.10.0-r13 |
| Chainguard | kubeflow-pipelines-apiserver | 0 | 2.16.0-r12 |
| Chainguard | kubeflow-volumes-web-app | 0 | 1.10.0-r12 |
| Chainguard | label-studio | 0 | 1.23.0-r1 |
| Chainguard | litellm | 0 | 1.82.3.0-r2 |
| Chainguard | metaflow-service | 0 | 2.5.0-r7 |
| Chainguard | metaflow-service-fips | 0 | 2.5.0-r1 |
| Chainguard | mlflow | 0 | 3.10.1-r1 |
| Chainguard | mlflow-iamguarded-compat | 0 | 3.10.1-r1 |
| Chainguard | opal | 0 | 0.9.4-r0 |
| Chainguard | opentelemetry-python-instrumentation | 0 | 0.60.1-r3 |
| Chainguard | pgadmin4 | 0 | 9.13-r3 |
| Chainguard | pgadmin4-fips | 0 | 9.13-r2 |
| Chainguard | py3.10-ambassador | 0 | 3.10.0-r26 |
| Chainguard | py3.11-ambassador | 0 | 3.10.0-r26 |
| Chainguard | py3.11-prefect | 0 | 3.6.23-r0 |
| Chainguard | py3.11-prefect-fips | 0 | 3.6.23-r0 |
| Chainguard | py3.12-ambassador | 0 | 3.10.0-r26 |
| Chainguard | py3.12-prefect | 0 | 3.6.23-r0 |
| Chainguard | py3.12-prefect-fips | 0 | 3.6.23-r0 |
| Chainguard | py3.13-ambassador | 0 | 3.10.0-r26 |
| Chainguard | py3.13-prefect | 0 | 3.6.23-r0 |
| Chainguard | py3.13-prefect-fips | 0 | 3.6.23-r0 |
| Chainguard | py3.14-prefect | 0 | 3.6.23-r0 |
| Chainguard | semgrep | 0 | 1.157.0-r1 |
| Chainguard | spamcheck | 0 | 3.5.3-r8 |
| Chainguard | superset-5.0 | 0 | 5.0.0-r22 |
| Chainguard | superset-6.0 | 0 | 6.0.0-r7 |
| Chainguard | tritonserver-backend-vllm-cuda-12.9 | 0 | 25.9.0_git20260318-r0 |
| Chainguard | vllm-openai-cuda-12.9 | 0 | 0.17.1-r1 |
| Chainguard | wazuh-manager-framework | 0 | 4.14.4-r1 |
| Wolfi | airflow-3 | 0 | 3.1.8-r10 |
| Wolfi | az | 0 | 2.84.0-r4 |
| Wolfi | checkov | 0 | 3.2.511-r0 |
| Wolfi | confluent-docker-utils | 0 | 0.0.169-r1 |
| Wolfi | dask-kubernetes | 0 | 2026.3.0-r2 |
| Wolfi | jupyter-base-notebook | 0 | 7.5.5-r1 |
| Wolfi | k8s-sidecar | 0 | 2.5.1-r3 |
| Wolfi | kserve-storage-controller | 0 | 0.16.0-r24 |
| Wolfi | kubeflow-jupyter-web-app | 0 | 1.10.0-r13 |
| Wolfi | kubeflow-pipelines-apiserver | 0 | 2.16.0-r12 |
| Wolfi | kubeflow-volumes-web-app | 0 | 1.10.0-r12 |
| Wolfi | mlflow | 0 | 3.10.1-r1 |
| Wolfi | mlflow-iamguarded-compat | 0 | 3.10.1-r1 |
| Wolfi | py3.10-ambassador | 0 | 3.10.0-r26 |
| Wolfi | py3.11-ambassador | 0 | 3.10.0-r26 |
| Wolfi | py3.12-ambassador | 0 | 3.10.0-r26 |
| Wolfi | py3.13-ambassador | 0 | 3.10.0-r26 |
| Wolfi | semgrep | 0 | 1.157.0-r1 |
| Wolfi | superset-5.0 | 0 | 5.0.0-r22 |
| Wolfi | superset-6.0 | 0 | 6.0.0-r7 |
| openSUSE:Leap 16.0 | python-requests | 0 | 2.32.4-160000.3.1 |
| openSUSE:Tumbleweed | python-requests | 0 | 2.33.0-1.1 |
Related vulnerabilities
- CVE-2026-34073 cryptography is a package designed to expose cryptographic primitives and recipes to… Also affects airflow-3
- CVE-2026-4539 A security flaw has been discovered in pygments up to 2.19.2. Also affects airflow-3
- CVE-2026-30922 pyasn1 is a generic ASN.1 library for Python. Also affects airflow-3
- CVE-2026-27448 pyOpenSSL is a Python wrapper around the OpenSSL library. Also affects airflow-3
- CVE-2026-27459 pyOpenSSL is a Python wrapper around the OpenSSL library. Also affects airflow-3
- CVE-2026-32597 PyJWT is a JSON Web Token implementation in Python. Also affects airflow-3
- CVE-2026-31958 Tornado is a Python web framework and asynchronous networking library. Also affects airflow-3
- CVE-2026-25604 In AWS Auth manager, the origin of the SAML authentication has been used as provided by… Also affects airflow-3