lowercase g in goose (#4832)

This commit is contained in:
Angie Jones
2025-09-26 23:44:38 -05:00
committed by GitHub
parent bb1b73d634
commit 2032c7099c
120 changed files with 669 additions and 651 deletions
+2 -2
View File
@@ -1,13 +1,13 @@
IMPORTANT: currently GOOSE_ALLOWLIST is used in main.ts in ui/desktop, and not in goose-server. The following is for reference in case it is used on the server side for launch time enforcement.
# Goose Extension Allowlist
# goose Extension Allowlist
The allowlist feature provides a security mechanism for controlling which MCP commands can be used by goose.
By default, goose will let you run any MCP via any command, which isn't always desired.
## How It Works
1. When enabled, Goose will only allow execution of commands that match entries in the allowlist
1. When enabled, goose will only allow execution of commands that match entries in the allowlist
2. Commands not in the allowlist will be rejected with an error message
3. The allowlist is fetched from a URL specified by the `GOOSE_ALLOWLIST` environment variable and cached while running.
+23 -23
View File
@@ -454,7 +454,7 @@ fn is_command_allowed_with_allowlist(
return true;
}
// If the path doesn't match, don't allow it
println!("Goosed not in expected directory: {}", cmd);
println!("goosed not in expected directory: {}", cmd);
println!("Expected path: {}", expected_path);
return false;
} else {
@@ -474,20 +474,20 @@ fn is_command_allowed_with_allowlist(
// Check against the allowlist
Some(extensions) => {
// Strip out the Goose app resources/bin prefix if present (handle both macOS and Windows paths)
// Strip out the goose app resources/bin prefix if present (handle both macOS and Windows paths)
let mut cmd_to_check = cmd.to_string();
let mut is_goose_path = false;
// Check for macOS-style Goose.app path
if cmd_to_check.contains("Goose.app/Contents/Resources/bin/") {
if let Some(idx) = cmd_to_check.find("Goose.app/Contents/Resources/bin/") {
// Check for macOS-style goose.app path
if cmd_to_check.contains("goose.app/Contents/Resources/bin/") {
if let Some(idx) = cmd_to_check.find("goose.app/Contents/Resources/bin/") {
cmd_to_check = cmd_to_check
[(idx + "Goose.app/Contents/Resources/bin/".len())..]
[(idx + "goose.app/Contents/Resources/bin/".len())..]
.to_string();
is_goose_path = true;
}
}
// Check for Windows-style Goose path with resources\bin
// Check for Windows-style goose path with resources\bin
else if cmd_to_check.to_lowercase().contains("\\resources\\bin\\")
|| cmd_to_check.contains("/resources/bin/")
{
@@ -507,7 +507,7 @@ fn is_command_allowed_with_allowlist(
}
}
// Only check current directory for non-Goose paths
// Only check current directory for non-goose paths
if !is_goose_path {
// Check that the command exists as a peer command to current executable directory
// Only apply this check if the command includes a path separator
@@ -524,7 +524,7 @@ fn is_command_allowed_with_allowlist(
if (first_part.contains('/') || first_part.contains('\\'))
&& normalized_cmd_path != expected_path
&& !cmd_to_check.contains("Goose.app/Contents/Resources/bin/")
&& !cmd_to_check.contains("goose.app/Contents/Resources/bin/")
{
println!("Command not in expected directory: {}", cmd);
return false;
@@ -801,15 +801,15 @@ mod tests {
&allowlist
));
// Test with shim path - 'Goose.app/Contents/Resources/bin/' and before can be stripped to get the command to match
// Test with shim path - 'goose.app/Contents/Resources/bin/' and before can be stripped to get the command to match
assert!(is_command_allowed_with_allowlist(
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/Goose.app/Contents/Resources/bin/uvx something",
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/goose.app/Contents/Resources/bin/uvx something",
&allowlist
));
// Test with shim path & latest version
assert!(is_command_allowed_with_allowlist(
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/Goose.app/Contents/Resources/bin/uvx something@latest",
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/goose.app/Contents/Resources/bin/uvx something@latest",
&allowlist
));
@@ -833,7 +833,7 @@ mod tests {
// Test with shim path & latest version
assert!(is_command_allowed_with_allowlist(
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/Goose.app/Contents/Resources/bin/npx -y mcp_hammer@latest start",
"/private/var/folders/fq/rd_cb6/T/AppTranslocation/EA0195/d/goose.app/Contents/Resources/bin/npx -y mcp_hammer@latest start",
&allowlist
));
}
@@ -941,15 +941,15 @@ mod tests {
// Test various Windows path formats
let test_paths = vec![
// Standard Windows path
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources\bin\uvx.exe",
r"C:\Users\MaxNovich\Downloads\goose-1.0.17\resources\bin\uvx.exe",
// Path with different casing
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\Resources\Bin\uvx.exe",
r"C:\Users\MaxNovich\Downloads\goose-1.0.17\Resources\Bin\uvx.exe",
// Path with forward slashes
r"C:/Users/MaxNovich/Downloads/Goose-1.0.17/resources/bin/uvx.exe",
r"C:/Users/MaxNovich/Downloads/goose-1.0.17/resources/bin/uvx.exe",
// Path with spaces
r"C:\Program Files\Goose 1.0.17\resources\bin\uvx.exe",
r"C:\Program Files\goose 1.0.17\resources\bin\uvx.exe",
// Path with version numbers
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe",
r"C:\Users\MaxNovich\Downloads\goose-1.0.17-block.202504072238-76ffe-win32-x64\goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe",
];
for path in test_paths {
@@ -975,9 +975,9 @@ mod tests {
// Path without resources\bin
r"C:\Users\MaxNovich\Downloads\uvx.exe",
// Path with modified resources\bin
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources_modified\bin\uvx.exe",
r"C:\Users\MaxNovich\Downloads\goose-1.0.17\resources_modified\bin\uvx.exe",
// Path with extra components
r"C:\Users\MaxNovich\Downloads\Goose-1.0.17\resources\bin\extra\uvx.exe",
r"C:\Users\MaxNovich\Downloads\goose-1.0.17\resources\bin\extra\uvx.exe",
];
for path in invalid_paths {
@@ -995,14 +995,14 @@ mod tests {
let allowlist = create_test_allowlist(&["uvx mcp_snowflake"]);
// Test Windows-style path with uvx.exe
let windows_path = r"C:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe";
let windows_path = r"C:\Users\MaxNovich\Downloads\goose-1.0.17-block.202504072238-76ffe-win32-x64\goose-1.0.17-block.202504072238-76ffe-win32-x64\resources\bin\uvx.exe";
let cmd = format!("{} mcp_snowflake@latest", windows_path);
// This should be allowed because it's a valid uvx command in the Goose resources/bin directory
// This should be allowed because it's a valid uvx command in the goose resources/bin directory
assert!(is_command_allowed_with_allowlist(&cmd, &allowlist));
// Test with different casing and backslashes
let windows_path_alt = r"c:\Users\MaxNovich\Downloads\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Goose-1.0.17-block.202504072238-76ffe-win32-x64\Resources\Bin\uvx.exe";
let windows_path_alt = r"c:\Users\MaxNovich\Downloads\goose-1.0.17-block.202504072238-76ffe-win32-x64\goose-1.0.17-block.202504072238-76ffe-win32-x64\Resources\Bin\uvx.exe";
let cmd_alt = format!("{} mcp_snowflake@latest", windows_path_alt);
assert!(is_command_allowed_with_allowlist(&cmd_alt, &allowlist));
}
+4 -4
View File
@@ -1149,7 +1149,7 @@
"properties": {
"bundled": {
"type": "boolean",
"description": "Whether this extension is bundled with Goose",
"description": "Whether this extension is bundled with goose",
"nullable": true
},
"description": {
@@ -1204,7 +1204,7 @@
},
"bundled": {
"type": "boolean",
"description": "Whether this extension is bundled with Goose",
"description": "Whether this extension is bundled with goose",
"nullable": true
},
"cmd": {
@@ -1251,7 +1251,7 @@
"properties": {
"bundled": {
"type": "boolean",
"description": "Whether this extension is bundled with Goose",
"description": "Whether this extension is bundled with goose",
"nullable": true
},
"display_name": {
@@ -1287,7 +1287,7 @@
"properties": {
"bundled": {
"type": "boolean",
"description": "Whether this extension is bundled with Goose",
"description": "Whether this extension is bundled with goose",
"nullable": true
},
"instructions": {