diff --git a/src/cortex-cli/src/run_cmd/execution.rs b/src/cortex-cli/src/run_cmd/execution.rs index 18bb58d5b..81384636b 100644 --- a/src/cortex-cli/src/run_cmd/execution.rs +++ b/src/cortex-cli/src/run_cmd/execution.rs @@ -17,6 +17,21 @@ use super::output::{copy_to_clipboard, send_notification}; use super::session::{SessionMode, resolve_session_id}; use super::system::check_file_descriptor_limits; +fn validate_attach_url(server_url: &str) -> Result<()> { + let parsed = reqwest::Url::parse(server_url).with_context(|| { + format!( + "--attach expects an HTTP(S) server URL, got '{server_url}'. Use --file/-f to attach local files." + ) + })?; + + match parsed.scheme() { + "http" | "https" => Ok(()), + _ => bail!( + "--attach expects an HTTP(S) server URL, got '{server_url}'. Use --file/-f to attach local files." + ), + } +} + impl RunCli { /// Run the command. pub async fn run(self) -> Result<()> { @@ -136,6 +151,7 @@ impl RunCli { // Execute based on whether we're attaching to a server or running locally if let Some(ref server_url) = self.attach { + validate_attach_url(server_url)?; self.run_attached(server_url, &message, &attachments, session_mode) .await } else { diff --git a/src/cortex-cli/tests/run_attach.rs b/src/cortex-cli/tests/run_attach.rs new file mode 100644 index 000000000..9230e4087 --- /dev/null +++ b/src/cortex-cli/tests/run_attach.rs @@ -0,0 +1,52 @@ +use std::process::Command; + +#[test] +fn run_attach_rejects_filesystem_paths() { + let output = Command::new(env!("CARGO_BIN_EXE_Cortex")) + .args([ + "run", + "--dry-run", + "--attach", + "/nonexistent/file.txt", + "test", + ]) + .output() + .expect("cortex binary should run"); + + assert!( + !output.status.success(), + "expected non-zero exit; stdout: {}; stderr: {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + + let stderr = String::from_utf8_lossy(&output.stderr); + assert!( + stderr.contains("--attach expects an HTTP(S) server URL"), + "stderr did not explain the invalid --attach value: {stderr}" + ); +} + +#[test] +fn run_attach_allows_http_server_urls() { + let output = Command::new(env!("CARGO_BIN_EXE_Cortex")) + .args([ + "run", + "--dry-run", + "--attach", + "http://localhost:3000", + "test", + ]) + .output() + .expect("cortex binary should run"); + + assert!( + output.status.success(), + "expected zero exit; stdout: {}; stderr: {}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + ); + + let stderr = String::from_utf8_lossy(&output.stderr); + assert!(stderr.contains("Server attachment not yet fully implemented")); +}