Skip to content

Commit 3e4417b

Browse files
committed
Reject secure serve URLs for inline app sandbox
Signed-off-by: Andrew Harvard <aharvard@squareup.com>
1 parent 5e9043d commit 3e4417b

1 file changed

Lines changed: 27 additions & 13 deletions

File tree

  • ui/goose2/src-tauri/src/commands

ui/goose2/src-tauri/src/commands/acp.rs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,10 @@ fn goose_serve_http_base_url(goose_serve_url: &str) -> Result<String, String> {
6565
.ok_or_else(|| format!("{GOOSE_SERVE_URL_ENV} must include a URL scheme"))?;
6666
let http_scheme = match scheme {
6767
"ws" => "http",
68-
"wss" => "https",
6968
"http" => "http",
70-
"https" => "https",
7169
_ => {
7270
return Err(format!(
73-
"{GOOSE_SERVE_URL_ENV} must use ws, wss, http, or https"
71+
"{GOOSE_SERVE_URL_ENV} must use ws or http for inline MCP apps because the app guest origin is served over local http"
7472
));
7573
}
7674
};
@@ -104,6 +102,12 @@ fn goose_serve_http_path_prefix(path: &str) -> String {
104102
}
105103

106104
fn ensure_configured_goose_serve_supports_inline_apps(goose_serve_url: &str) -> Result<(), String> {
105+
if !goose_serve_url_uses_plaintext_http(goose_serve_url)? {
106+
return Err(format!(
107+
"{GOOSE_SERVE_URL_ENV} must use ws or http for inline MCP apps because the app guest origin is served over local http"
108+
));
109+
}
110+
107111
if goose_serve_url_is_loopback(goose_serve_url)? {
108112
return Ok(());
109113
}
@@ -113,6 +117,14 @@ fn ensure_configured_goose_serve_supports_inline_apps(goose_serve_url: &str) ->
113117
))
114118
}
115119

120+
fn goose_serve_url_uses_plaintext_http(goose_serve_url: &str) -> Result<bool, String> {
121+
let (scheme, _) = goose_serve_url
122+
.trim()
123+
.split_once("://")
124+
.ok_or_else(|| format!("{GOOSE_SERVE_URL_ENV} must include a URL scheme"))?;
125+
Ok(matches!(scheme, "ws" | "http"))
126+
}
127+
116128
fn goose_serve_url_is_loopback(goose_serve_url: &str) -> Result<bool, String> {
117129
let (_, rest) = goose_serve_url
118130
.trim()
@@ -160,20 +172,20 @@ mod tests {
160172
"http://127.0.0.1:12345"
161173
);
162174
assert_eq!(
163-
goose_serve_http_base_url("wss://example.test/acp").unwrap(),
164-
"https://example.test"
175+
goose_serve_http_base_url("http://localhost:3000/acp").unwrap(),
176+
"http://localhost:3000"
165177
);
166178
}
167179

168180
#[test]
169181
fn preserves_path_prefix_from_websocket_url() {
170182
assert_eq!(
171-
goose_serve_http_base_url("wss://example.test/goose/acp").unwrap(),
172-
"https://example.test/goose"
183+
goose_serve_http_base_url("ws://localhost:3000/goose/acp").unwrap(),
184+
"http://localhost:3000/goose"
173185
);
174186
assert_eq!(
175-
goose_serve_http_base_url("wss://example.test/goose/acp?token=abc").unwrap(),
176-
"https://example.test/goose"
187+
goose_serve_http_base_url("http://localhost:3000/goose/acp?token=abc").unwrap(),
188+
"http://localhost:3000/goose"
177189
);
178190
}
179191

@@ -183,16 +195,14 @@ mod tests {
183195
goose_serve_http_base_url("http://localhost:3000").unwrap(),
184196
"http://localhost:3000"
185197
);
186-
assert_eq!(
187-
goose_serve_http_base_url("https://localhost:3000/goose").unwrap(),
188-
"https://localhost:3000/goose"
189-
);
190198
}
191199

192200
#[test]
193201
fn rejects_invalid_goose_serve_url() {
194202
assert!(goose_serve_http_base_url("localhost:3000").is_err());
195203
assert!(goose_serve_http_base_url("ftp://localhost:3000/acp").is_err());
204+
assert!(goose_serve_http_base_url("wss://localhost:3000/acp").is_err());
205+
assert!(goose_serve_http_base_url("https://localhost:3000/acp").is_err());
196206
assert!(goose_serve_http_base_url("ws:///acp").is_err());
197207
}
198208

@@ -212,5 +222,9 @@ mod tests {
212222
assert!(
213223
ensure_configured_goose_serve_supports_inline_apps("wss://example.test/acp").is_err()
214224
);
225+
assert!(
226+
ensure_configured_goose_serve_supports_inline_apps("wss://localhost:12345/acp")
227+
.is_err()
228+
);
215229
}
216230
}

0 commit comments

Comments
 (0)