VYPR
High severityNVD Advisory· Published Mar 23, 2026· Updated Mar 24, 2026

Salvo has a Path Traversal in salvo-proxy::encode_url_path allows API Gateway Bypass

CVE-2026-33242

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.

PackageAffected versionsPatched versions
salvocrates.io
>= 0.39.0, < 0.89.30.89.3

Affected products

1

Patches

1
7bac30e69603

Fix Unable to resolve URL-encoded paths #190

https://github.com/salvo-rs/salvoChrislearn YoungNov 28, 2022via ghsa
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

News mentions

0

No linked articles in our index yet.