diff --git a/server-rs/crates/preview-deployer-server/src/jenkins.rs b/server-rs/crates/preview-deployer-server/src/jenkins.rs index fb4f45437..840c4a0f0 100644 --- a/server-rs/crates/preview-deployer-server/src/jenkins.rs +++ b/server-rs/crates/preview-deployer-server/src/jenkins.rs @@ -274,11 +274,27 @@ impl JenkinsClient { } fn resolve_trusted_url(&self, value: &str) -> Result { - let url = Url::parse(value) + let returned = Url::parse(value) .or_else(|_| self.job_url.join(value)) .map_err(|_| "Jenkins 返回了无效 URL".to_string())?; - self.ensure_same_origin(&url)?; - Ok(url) + if !returned.username().is_empty() + || returned.password().is_some() + || !returned.path().starts_with(self.root_url.path()) + { + return Err("Jenkins 返回了非受信源 URL".to_string()); + } + let relative_path = returned + .path() + .strip_prefix(self.root_url.path()) + .ok_or_else(|| "Jenkins 返回了非受信路径".to_string())?; + let mut trusted = self + .root_url + .join(relative_path) + .map_err(|_| "Jenkins 返回了无效 URL".to_string())?; + trusted.set_query(returned.query()); + trusted.set_fragment(None); + self.ensure_same_origin(&trusted)?; + Ok(trusted) } fn ensure_same_origin(&self, url: &Url) -> Result<(), String> { diff --git a/server-rs/crates/preview-deployer-server/src/tests.rs b/server-rs/crates/preview-deployer-server/src/tests.rs index cbb117687..d78e065e2 100644 --- a/server-rs/crates/preview-deployer-server/src/tests.rs +++ b/server-rs/crates/preview-deployer-server/src/tests.rs @@ -95,7 +95,7 @@ async fn mock_trigger( async fn mock_queue(axum::extract::Path(id): axum::extract::Path) -> Json { Json( - json!({"cancelled": false, "executable": {"url": format!("/jenkins/job/shared/job/Genarrative-Preview-Deployer/{id}/")}}), + json!({"cancelled": false, "executable": {"url": format!("http://192.168.35.82:8080/jenkins/job/shared/job/Genarrative-Preview-Deployer/{id}/")}}), ) }