fix(security): validate space name in chat +send (#444)

Add validate_resource_name() to the --space argument in chat +send,
consistent with the validation already applied in gmail +watch,
events +subscribe, and modelarmor helpers. Prevents path traversal
and query injection via the space parameter.
This commit is contained in:
Anshul Garg
2026-03-14 01:23:15 +05:30
committed by GitHub
parent 8448c1aac1
commit bb94016dd8
2 changed files with 30 additions and 11 deletions
@@ -0,0 +1,5 @@
---
"@googleworkspace/cli": patch
---
fix(security): validate space name in chat +send to prevent path traversal
+25 -11
View File
@@ -72,7 +72,7 @@ TIPS:
Box::pin(async move {
if let Some(matches) = matches.subcommand_matches("+send") {
// Parse arguments into our config struct config
let config = parse_send_args(matches);
let config = parse_send_args(matches)?;
// The `?` operator here will propagate any errors from `build_send_request`
// immediately, returning `Err(GwsError)` from the async block.
let (params_str, body_str, scopes) = build_send_request(&config, doc)?;
@@ -175,14 +175,14 @@ pub struct SendConfig {
/// # Returns
///
/// * `SendConfig` - The populated configuration struct.
pub fn parse_send_args(matches: &ArgMatches) -> SendConfig {
SendConfig {
// We clone the strings here because ArgMatches owns the original strings,
// and we need to pass ownership of these values to our config struct
// to decouple it from the clap lifetime.
space: matches.get_one::<String>("space").unwrap().clone(),
pub fn parse_send_args(matches: &ArgMatches) -> Result<SendConfig, GwsError> {
let space = matches.get_one::<String>("space").unwrap().clone();
crate::validate::validate_resource_name(&space)?;
Ok(SendConfig {
space,
text: matches.get_one::<String>("text").unwrap().clone(),
}
})
}
#[cfg(test)]
@@ -241,12 +241,26 @@ mod tests {
#[test]
fn test_parse_send_args() {
let matches = make_matches_send(&["test", "--space", "s", "--text", "t"]);
let config = parse_send_args(&matches);
assert_eq!(config.space, "s");
let matches = make_matches_send(&["test", "--space", "valid-space", "--text", "t"]);
let config = parse_send_args(&matches).unwrap();
assert_eq!(config.space, "valid-space");
assert_eq!(config.text, "t");
}
#[test]
fn test_parse_send_args_rejects_traversal_in_space() {
let matches = make_matches_send(&["test", "--space", "../etc/passwd", "--text", "t"]);
let result = parse_send_args(&matches);
assert!(result.is_err(), "space with path traversal should be rejected");
}
#[test]
fn test_parse_send_args_rejects_query_injection_in_space() {
let matches = make_matches_send(&["test", "--space", "spaces/AAA?key=injected", "--text", "t"]);
let result = parse_send_args(&matches);
assert!(result.is_err(), "space with query characters should be rejected");
}
#[test]
fn test_inject_commands() {
let helper = ChatHelper;