Arbitrary file read un Vapor
Description
Vapor FileMiddleware before 4.29.4 allows path traversal via percent-encoded relative paths, enabling arbitrary file read on the host.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Vapor FileMiddleware before 4.29.4 allows path traversal via percent-encoded relative paths, enabling arbitrary file read on the host.
Vulnerability
Overview
CVE-2020-15230 is a path traversal vulnerability in Vapor's FileMiddleware component. The root cause is that FileMiddleware did not properly decode percent-encoded characters before checking for relative path segments. Specifically, sequences like %2e%2e (which decodes to ..) were not recognized as directory traversal attempts, allowing attackers to bypass the intended path restrictions [1][4].
Exploitation
An attacker can exploit this by sending HTTP requests with percent-encoded relative path segments, such as %2e%2e/ or %2e%2e%2f, to any endpoint served by FileMiddleware. No authentication is required if the vulnerable endpoint is publicly accessible. Only applications that explicitly use FileMiddleware are affected [2].
Impact
Successful exploitation allows an attacker to read arbitrary files from the filesystem of the host running the Vapor application. This could expose sensitive information including configuration files, source code, environment variables, or credentials, potentially leading to further compromise [2].
Mitigation
The vulnerability is fixed in Vapor version 4.29.4. Users are strongly advised to upgrade to this version or later. No workaround is documented; the only complete fix is to apply the patch that properly decodes percent-encoded characters before path validation [1][2].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/vapor/vaporSwiftURL | >= 4.0.0-rc.2.5, < 4.29.4 | 4.29.4 |
Affected products
2Patches
1cf1651f7ff76fix relative percent decoding in file middleware (#2500)
3 files changed · +21 −3
Sources/Vapor/Middleware/FileMiddleware.swift+5 −3 modified@@ -13,8 +13,10 @@ public final class FileMiddleware: Middleware { /// See `Middleware`. public func respond(to request: Request, chainingTo next: Responder) -> EventLoopFuture<Response> { - // make a copy of the path - var path = request.url.path + // make a copy of the percent-decoded path + guard var path = request.url.path.removingPercentEncoding else { + return request.eventLoop.makeFailedFuture(Abort(.badRequest)) + } // path must be relative. while path.hasPrefix("/") { @@ -27,7 +29,7 @@ public final class FileMiddleware: Middleware { } // create absolute file path - let filePath = self.publicDirectory + (path.removingPercentEncoding ?? path) + let filePath = self.publicDirectory + path // check if file exists and is not a directory var isDir: ObjCBool = false
Tests/VaporTests/FileTests.swift+15 −0 modified@@ -61,4 +61,19 @@ final class FileTests: XCTestCase { XCTAssertEqual(res.body.string, "<h1>Hello</h1>\n") } } + + func testPercentDecodedRelativePath() throws { + let app = Application(.testing) + defer { app.shutdown() } + + let path = #file.split(separator: "/").dropLast().joined(separator: "/") + app.middleware.use(FileMiddleware(publicDirectory: "/" + path)) + + try app.test(.GET, "%2e%2e/VaporTests/Utilities/foo.txt") { res in + XCTAssertEqual(res.status, .forbidden) + }.test(.GET, "Utilities/foo.txt") { res in + XCTAssertEqual(res.status, .ok) + XCTAssertEqual(res.body.string, "bar\n") + } + } }
Tests/VaporTests/Utilities/foo.txt+1 −0 added@@ -0,0 +1 @@ +bar
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-vcvg-xgr8-p5gqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-15230ghsaADVISORY
- github.com/vapor/vapor/commit/cf1651f7ff76515593f4d8ca6e6e15d2247fe255ghsax_refsource_MISCWEB
- github.com/vapor/vapor/pull/2500ghsax_refsource_MISCWEB
- github.com/vapor/vapor/security/advisories/GHSA-vcvg-xgr8-p5gqghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.