CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-69226

aiohttp Static Resource Path Traversal and Existence Oracle

Alon Barad
Alon Barad
Software Engineer

Feb 28, 2026·5 min read·47 visits

Executive Summary (TL;DR)

aiohttp <= 3.13.2 allows attackers to map the filesystem via `web.static()` routes. By sending path traversal requests, attackers can distinguish between existing files (403 Forbidden) and missing files (404 Not Found) outside the static root. Fixed in 3.13.3.

A path traversal vulnerability exists in aiohttp versions 3.13.2 and earlier within the `web.static()` route definition. Due to improper path normalization during the request routing phase, the application fails to correctly filter requests containing traversal sequences (e.g., `../`). While the underlying file handler prevents reading content outside the static root, it returns distinct HTTP status codes for existing versus non-existing files. This discrepancy creates a side-channel oracle, allowing unauthenticated remote attackers to enumerate the server's filesystem structure.

Vulnerability Overview

CVE-2025-69226 affects aiohttp, a widely used asynchronous HTTP client/server framework for Python. The vulnerability resides specifically in the UrlDispatcher.add_static method and the associated StaticResource class, which are responsible for serving static files from a designated directory.

In versions 3.13.2 and prior, the routing logic allows requests with traversal sequences (e.g., /static/../../etc/passwd) to pass the initial URL matching phase. Although the subsequent file handling logic blocks access to the file content, it inadvertently leaks information about the file's existence. When an attacker requests a file that exists outside the static root, the server responds with 403 Forbidden. Conversely, if the file does not exist, the server responds with 404 Not Found.

This behavior classifies the issue as an Existence Oracle (CWE-200: Exposure of Sensitive Information to an Unauthorized Actor) facilitated by Path Traversal (CWE-22). While it does not permit arbitrary file read (Confidentiality impact is Low), it enables attackers to brute-force directory structures and identify the presence of sensitive files, config files, or logs on the host system.

Root Cause Analysis

The root cause lies in a logical discrepancy between the routing phase (resolve) and the handling phase (_handle) of a request.

The StaticResource class in aiohttp determines if a request matches a defined static route. In vulnerable versions, the resolve method simply checked if the raw requested URL path started with the configured static prefix (e.g., /static/). It did not normalize the path before this check. Consequently, a request for /static/../secret would satisfy the prefix check (/static/) and be routed to the static file handler.

Once the request reached the handler, aiohttp performed security checks to ensure the resolved path did not escape the root directory. If the path resolved to a file outside the root, the handler raised an HTTPForbidden (403) exception. If the path did not resolve to a file at all, the standard behavior for a static handler is to return HTTPNotFound (404).

This separation of concerns created the oracle: the router was too permissive, accepting traversal paths that the handler would later reject for security reasons. The difference in rejection methods (403 for security violation vs. 404 for missing file) provided the side channel.

Code Analysis

The fix was implemented in aiohttp/web_urldispatcher.py by introducing path normalization directly into the routing logic. This ensures that any path attempting to traverse out of the static prefix is detected before it is matched to the handler.

Below is the analysis of the patch in StaticResource.resolve:

# aiohttp/web_urldispatcher.py
 
async def resolve(self, request: Request) -> _Resolve:
    path = request.rel_url.path_safe
    method = request.method
    
    # [PATCH] Normalization added here
    # We normalise here to avoid matches that traverse below the static root.
    # e.g. /static/../../../../home/user/webapp/static/
    norm_path = os.path.normpath(path)
    if IS_WINDOWS:
        norm_path = norm_path.replace("\\", "/")
    
    # [PATCH] Check against normalized path instead of raw path
    # If the normalized path has traversed out (e.g., becomes "/etc/passwd"),
    # it will no longer start with "/static/", failing this check.
    if not norm_path.startswith(self._prefix2) and norm_path != self._prefix:
        return None, set()
        
    # ... rest of resolution logic

By normalizing path to norm_path using os.path.normpath, sequences like /static/../ are resolved immediately. If the resulting path does not start with the required prefix, the router returns None. This causes the server to return a 404 Not Found for the URL, making the response indistinguishable from a request for a non-existent page.

Exploitation Mechanics

Exploiting this vulnerability requires sending HTTP GET requests to a known static file endpoint. The attacker does not need authentication. The goal is to identify if specific files exist on the server.

Scenario: A server has static files mapped to /static/.

Step 1: Probe for existing system file The attacker sends: GET /static/../../../../etc/passwd HTTP/1.1

  • Vulnerable Server: Returns 403 Forbidden. This confirms /etc/passwd exists.
  • Patched Server: Returns 404 Not Found. The server denies knowledge of this path.

Step 2: Probe for non-existent file The attacker sends: GET /static/../../../../etc/doesnotexist HTTP/1.1

  • Vulnerable Server: Returns 404 Not Found.
  • Patched Server: Returns 404 Not Found.

By automating these requests with a wordlist of common files (e.g., config files, source code, SSH keys), an attacker can map the directory structure. This information is valuable for chaining attacks, such as identifying the location of a configuration file to target with a separate local file inclusion (LFI) vulnerability.

Remediation & Mitigation

The primary remediation is to upgrade the aiohttp library to version 3.13.3 or later. This version includes the patch that enforces path normalization within the StaticResource.resolve method.

Installation:

pip install aiohttp>=3.13.3

Configuration Best Practices: The aiohttp documentation and security advisories consistently recommend against using web.static() for serving static files in production environments. This feature is intended for development convenience.

For production deployments, static files should be served by a dedicated reverse proxy (such as Nginx or Apache) or a Content Delivery Network (CDN). These specialized servers have more robust, battle-tested path handling logic and performance optimizations. Moving static file serving to a reverse proxy effectively mitigates this class of vulnerability within the application layer.

Official Patches

aio-libsOfficial patch commit

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
EPSS Probability
0.06%
Top 81% most exploited

Affected Systems

aiohttp <= 3.13.2

Affected Versions Detail

Product
Affected Versions
Fixed Version
aiohttp
aio-libs
<= 3.13.23.13.3
AttributeDetail
CWE IDCWE-22
CWE NameImproper Limitation of a Pathname to a Restricted Directory
CVSS v3.15.3 (Medium)
Attack VectorNetwork
ImpactInformation Disclosure (Existence Oracle)
EPSS Score0.00061 (Low)

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1190Exploit Public-Facing Application
Initial Access
CWE-22
Path Traversal

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Known Exploits & Detection

N/ANo public exploit code available; vulnerability is an info leak oracle.

Vulnerability Timeline

Patch committed to main branch
2026-01-03
CVE-2025-69226 Published
2026-01-05
Version 3.13.3 Released
2026-01-05

References & Sources

  • [1]GHSA-54jq-c3m8-4m76 Advisory
  • [2]NVD CVE-2025-69226

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 10 hours ago•CVE-2026-39922
6.3

CVE-2026-39922: Server-Side Request Forgery in GeoNode Service Registration Endpoint

GeoNode versions prior to 4.4.5 and 5.0.2 are vulnerable to Server-Side Request Forgery (SSRF) in the service registration endpoint. Authenticated attackers with low privileges can exploit insufficient input validation in the Web Map Service (WMS) registration module to force the application server to make outbound network queries to loopback addresses, private RFC1918 subnets, link-local scopes, and cloud metadata endpoints. This technical report details the mechanics of the vulnerability, the underlying architectural flaw, and how to effectively remediate and mitigate the associated security risks.

Alon Barad
Alon Barad
4 views•7 min read
•about 19 hours ago•CVE-2022-0492
7.8

CVE-2022-0492: Privilege Escalation and Container Escape via cgroups v1 release_agent

CVE-2022-0492 is a high-severity missing authorization vulnerability in the Linux kernel's Control Groups (cgroups) v1 implementation. The flaw resides within the cgroup_release_agent_write function in kernel/cgroup/cgroup-v1.c, where the kernel fails to validate if the process writing to the release_agent file possesses administrative capabilities in the initial user namespace. This allows a local attacker inside a container with root privileges (UID 0) to abuse user namespaces, mount a cgroups v1 directory, modify the release_agent parameter, and execute arbitrary commands on the host system as host root, effectively achieving a complete container escape.

Amit Schendel
Amit Schendel
8 views•7 min read
•3 days ago•GHSA-G72G-R7M4-9X4G
6.3

GHSA-G72G-R7M4-9X4G: Insufficient Session Expiration of OAuth Tokens in NocoDB

NocoDB is subject to an insufficient session expiration vulnerability where OAuth access and refresh tokens are not invalidated or revoked during security-sensitive actions such as password changes, forgot-password requests, or password resets. This allows an attacker possessing an active OAuth token to maintain unauthorized persistence.

Amit Schendel
Amit Schendel
11 views•6 min read
•3 days ago•GHSA-FGMC-2HQJ-86V4
6.9

GHSA-FGMC-2HQJ-86V4: Default Administrative Credentials in vantage6-server

A vulnerability in the vantage6 federated learning framework allows unauthenticated remote attackers to gain administrative control of the server via hardcoded default credentials (root/root) when deployed under default configurations in versions 4.2.3 and below.

Amit Schendel
Amit Schendel
8 views•5 min read
•3 days ago•GHSA-X9F6-9RVM-MMRG
6.9

GHSA-X9F6-9RVM-MMRG: Improper Access Control and Volume Mount Isolation Bypass in vantage6 Node

An improper access control vulnerability in the vantage6 node component allows concurrently running algorithm containers to read and modify sensitive input and output files of other tasks. The lack of strict workspace directory isolation exposes a significant attack surface in multi-tenant or federated environments where untrusted algorithms are executed.

Amit Schendel
Amit Schendel
3 views•4 min read
•3 days ago•CVE-2026-47760
8.7

CVE-2026-47760: Cross-Site Scripting (XSS) via SVG Namespace Sanitizer Bypass in TinyMCE

TinyMCE versions 6.8.0 through 7.0.1 contain a high-severity Cross-Site Scripting (XSS) vulnerability. The flaw exists in the custom HTML parser and sanitizer module, which incorrectly manages SVG namespace scopes when parsing nested elements. A low-privileged or unauthenticated attacker can submit a crafted HTML payload containing nested SVG structures to bypass sanitization filters, leading to arbitrary JavaScript execution in the context of the victim's browser session.

Alon Barad
Alon Barad
30 views•7 min read