-
Notifications
You must be signed in to change notification settings - Fork 5.9k
feat: allowlist optionally for goosed #1848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
505b2d6
4450de4
f61f4f4
7e97652
88a4fb7
6234422
4d6b997
070877a
acc0967
30cdcb5
4209479
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| # Goose Extension Allowlist | ||
|
|
||
| This document describes the extension allowlist feature in goose-server, which provides a security mechanism for controlling which commands can be executed by extensions. | ||
|
|
||
| ## Overview | ||
|
|
||
| The allowlist feature enables administrators to restrict which commands can be executed by Stdio extensions in Goose. This is an important security measure that prevents potentially malicious extensions from executing unauthorized commands on the system. | ||
|
|
||
| When enabled, the server will only allow execution of commands that match entries in the allowlist. Commands that are not in the allowlist will be rejected with an error message. | ||
|
|
||
| ## How It Works | ||
|
|
||
| 1. The allowlist is fetched from a URL specified by the `GOOSE_ALLOWLIST` environment variable. | ||
| 2. The allowlist is a YAML file that contains a list of allowed extension commands. | ||
| 3. The allowlist is fetched once when first needed and cached for the lifetime of the server. | ||
| 4. When a Stdio extension is registered, the command is checked against the allowlist. | ||
| 5. If the command is not in the allowlist, the extension registration is rejected. | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Setting the Allowlist URL | ||
|
|
||
| Set the `GOOSE_ALLOWLIST` environment variable to the URL of your allowlist YAML file: | ||
|
|
||
| ```bash | ||
| export GOOSE_ALLOWLIST=https://example.com/goose-allowlist.yaml | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how would the env var be passed into goosed? is it going to be built into the app?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, built into app, similar to other ones. |
||
| ``` | ||
|
|
||
| If this environment variable is not set, no allowlist restrictions will be applied (all commands will be allowed). | ||
|
|
||
| ### Allowlist File Format | ||
|
|
||
| The allowlist file should be a YAML file with the following structure: | ||
|
|
||
| ```yaml | ||
| extensions: | ||
| - id: extension-id-1 | ||
| command: command-name-1 | ||
| - id: extension-id-2 | ||
| command: command-name-2 | ||
| # ... more extensions | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ```yaml | ||
| extensions: | ||
| - id: slack | ||
| command: uvx mcp_slack | ||
| - id: github | ||
| command: uvx mcp_github | ||
| - id: jira | ||
| command: uvx mcp_jira | ||
| ``` | ||
|
|
||
| ### Command Matching | ||
|
|
||
| When a Stdio extension attempts to register with a command, the system: | ||
|
|
||
| 1. Extracts the base command name (the last part of the path) | ||
| - For example, `/Users/username/bin/mcp thing-here` becomes `mcp thing-here` | ||
|
michaelneale marked this conversation as resolved.
Outdated
|
||
| 2. Checks if this base command **exactly matches** any of the command strings in the allowlist | ||
| 3. Allows the extension if there's a match, rejects it otherwise | ||
|
|
||
| ### Special Cases | ||
|
|
||
| There are a few special cases in the command matching logic: | ||
|
|
||
| 1. **goosed commands**: Any command that is either exactly "goosed" or ends with "/goosed" is always allowed, regardless of the allowlist. This ensures that the Goose server itself can always be executed. | ||
|
|
||
| 2. **No allowlist**: If no allowlist is configured (the `GOOSE_ALLOWLIST` environment variable is not set), all commands are allowed. | ||
|
|
||
| 3. **Empty allowlist**: If the allowlist is empty (contains no entries), all commands are allowed. | ||
|
|
||
| ### Best Practices for Defining Allowlist Entries | ||
|
|
||
| To effectively use the allowlist with exact matching: | ||
|
|
||
| 1. **Be specific**: Define the exact command string that you want to allow. | ||
| 2. **Include full paths if needed**: If you want to allow a command only from a specific path, include the full path in the allowlist. | ||
| 3. **Regular auditing**: Regularly audit your allowlist to ensure it only contains the commands you intend to allow. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| 1. **HTTPS**: Always use HTTPS URLs for your allowlist to prevent man-in-the-middle attacks. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably validate this in the code too right?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
| 2. **Access Control**: Ensure the allowlist URL is only accessible to authorized users. | ||
| 3. **Validation**: The allowlist file should be carefully reviewed to ensure only trusted commands are included. | ||
| 4. **Monitoring**: Monitor extension registrations for any rejected commands, which might indicate attempted abuse. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| If extensions are being rejected unexpectedly: | ||
|
|
||
| 1. Check if the `GOOSE_ALLOWLIST` environment variable is set correctly. | ||
| 2. Verify that the allowlist file is accessible from the server. | ||
| 3. Ensure the allowlist file is properly formatted YAML. | ||
| 4. Check server logs for any errors related to fetching or parsing the allowlist. | ||
| 5. Verify that the command in the extension registration exactly matches what's in the allowlist. | ||
|
|
||
| ## Example Usage | ||
|
|
||
| 1. Create and host an allowlist file: | ||
|
|
||
| ```yaml | ||
| # allowlist.yaml | ||
| extensions: | ||
| - id: slack | ||
| command: uvx mcp_slack | ||
| - id: github | ||
| command: uvx mcp_github | ||
| ``` | ||
|
|
||
| 2. Start goose-server with the allowlist URL: | ||
|
|
||
| ```bash | ||
| export GOOSE_ALLOWLIST=https://secure-server.example.com/allowlist.yaml | ||
| ./goosed | ||
| ``` | ||
|
|
||
| 3. When extensions are registered, only those with commands matching the allowlist will be accepted. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pairs of extension IDs + Commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes it is technically that (although id doesn't carry any intrinsic meaning)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we may want to validate both. In a world where IDs are unique I could see this being better long term validation (as you rightly point out no short term impact)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for now, just extension command until we know what id's are for!