Salvo has a Path Traversal in salvo-proxy::encode_url_path allows API Gateway Bypass
Description
Salvo is a Rust web framework. Versions 0.39.0 through 0.89.2 have a Path Traversal and Access Control Bypass vulnerability in the salvo-proxy component. The vulnerability allows an unauthenticated external attacker to bypass proxy routing constraints and access unintended backend paths (e.g., protected endpoints or administrative dashboards). This issue stems from the encode_url_path function, which fails to normalize "../" sequences and inadvertently forwards them verbatim to the upstream server by not re-encoding the "." character. Version 0.89.3 contains a patch.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
salvocrates.io | >= 0.39.0, < 0.89.3 | 0.89.3 |
Affected products
1Patches
17bac30e69603Fix Unable to resolve URL-encoded paths #190
2 files changed · +16 −6
crates/proxy/Cargo.toml+1 −0 modified@@ -25,6 +25,7 @@ fastrand.workspace = true hyper = { workspace = true, features = ["server", "http1", "http2"] } hyper-rustls = { workspace = true, features = ["http1", "http2", "webpki-tokio"] } once_cell.workspace = true +percent-encoding.workspace = true [dev-dependencies] salvo_core = { workspace = true, features = ["test"] }
crates/proxy/src/lib.rs+15 −6 modified@@ -6,16 +6,25 @@ use hyper::client::{Client, HttpConnector}; use hyper::upgrade::OnUpgrade; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; use once_cell::sync::OnceCell; -use salvo_core::http::uri::{Uri, Scheme}; +use percent_encoding::{utf8_percent_encode, CONTROLS}; use salvo_core::http::header::{HeaderMap, HeaderName, HeaderValue, CONNECTION, HOST, UPGRADE}; +use salvo_core::http::uri::{Scheme, Uri}; use salvo_core::http::StatusCode; -use salvo_core::http::{ReqBody, ResBody, Body}; +use salvo_core::http::{Body, ReqBody, ResBody}; use salvo_core::{async_trait, BoxedError, Depot, Error, FlowCtrl, Handler, Request, Response}; use tokio::io::copy_bidirectional; type HyperRequest = hyper::Request<ReqBody>; type HyperResponse = hyper::Response<ResBody>; +#[inline] +pub(crate) fn encode_url_path(path: &str) -> String { + path.split('/') + .map(|s| utf8_percent_encode(s, CONTROLS).to_string()) + .collect::<Vec<_>>() + .join("/") +} + /// Upstreams trait. pub trait Upstreams: Send + Sync + 'static { /// Error type. @@ -103,8 +112,8 @@ where } let param = req.params().iter().find(|(key, _)| key.starts_with('*')); - let mut rest: Cow<'_, str> = if let Some((_, rest)) = param { - rest.into() + let mut rest = if let Some((_, rest)) = param { + encode_url_path(rest) } else { "".into() }; @@ -285,8 +294,8 @@ mod tests { #[tokio::test] async fn test_proxy() { - let router = - Router::new().push(Router::with_path("rust/<**rest>").handle(Proxy::new(vec!["https://www.rust-lang.org"]))); + let router = Router::new() + .push(Router::with_path("rust/<**rest>").handle(Proxy::new(vec!["https://www.rust-lang.org"]))); let content = TestClient::get("http://127.0.0.1:7979/rust/tools/install") .send(router)
Vulnerability mechanics
Generated by null/stub 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-f842-phm9-p4v4ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-33242ghsaADVISORY
- github.com/salvo-rs/salvo/commit/7bac30e6960355c58e358e402072d4a3e5c4e1bbghsax_refsource_MISCWEB
- github.com/salvo-rs/salvo/releases/tag/v0.89.3ghsax_refsource_MISCWEB
- github.com/salvo-rs/salvo/security/advisories/GHSA-f842-phm9-p4v4ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.