fix: safety guard incorrectly blocks commands with URLs#1254
fix: safety guard incorrectly blocks commands with URLs#1254alexhoshina merged 4 commits intosipeed:mainfrom
Conversation
The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203
nikolasdehor
left a comment
There was a problem hiding this comment.
Clean fix for a legitimate false positive in the safety guard. URLs containing // after the scheme (e.g., https://github.com) were being matched as absolute paths.
The fix is minimal and correct: skipping matches that start with // avoids treating URL path components as filesystem paths. This is safe because:
- No legitimate absolute filesystem path starts with
//in normal usage - UNC paths (Windows
\\server\share) use backslashes, not forward slashes
The test coverage is good: 6 different URL schemes/commands are tested, covering https, http, ftp, and various tools (curl, wget, git clone, browser).
One minor note: // is technically a valid path on Unix (POSIX says it's implementation-defined and may refer to network paths on some systems like Cygwin). In practice, this edge case is negligible and not worth complicating the fix for.
LGTM.
|
Thanks for the review Nicolas, I guess we need another reviewer |
The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254
|
|
…bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
| for _, scheme := range webSchemes { | ||
| if strings.HasSuffix(before, scheme) { |
There was a problem hiding this comment.
nit: HTTPS:example.com will be blocked. This issue does not affect merging; it is merely a minor detail.
| commands := []string{ | ||
| "agent-browser open https://github.com", | ||
| "curl https://api.example.com/data", | ||
| "wget http://example.com/file", | ||
| "browser open https://github.com/user/repo", | ||
| "fetch ftp://ftp.example.com/file.txt", | ||
| "git clone https://github.com/sipeed/picoclaw.git", | ||
| } |
There was a problem hiding this comment.
nit: Real network requests may cause the exec tool to time out or slow down the CI.
|
Thanks @alexhoshina for the thorough review! Happy to follow up with separate PRs for any remaining nits, would appreciate a merge when you get a chance! |
|
@hkc5 Clean fix for the URL false positive in the safety guard. The regex matching //github.com from URLs as an absolute path is a subtle edge case. Simple check for the // prefix handles it well. We have a PicoClaw Dev Group on Discord where contributors can connect and collaborate. If you're interested, send an email to |
* fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203 * fix: handle file:// URIs correctly in safety guard The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254 * style: fix gofumpt formatting * fix(safety-guard): use exact match position to prevent URL exemption bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
* fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203 * fix: handle file:// URIs correctly in safety guard The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254 * style: fix gofumpt formatting * fix(safety-guard): use exact match position to prevent URL exemption bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
* fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203 * fix: handle file:// URIs correctly in safety guard The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254 * style: fix gofumpt formatting * fix(safety-guard): use exact match position to prevent URL exemption bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
* fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203 * fix: handle file:// URIs correctly in safety guard The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254 * style: fix gofumpt formatting * fix(safety-guard): use exact match position to prevent URL exemption bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
* fix: safety guard incorrectly blocks commands with URLs The absolutePathPattern regex was matching URL path components like //github.com as file system paths, causing commands containing URLs to be incorrectly blocked by the workspace restriction safety guard. For example, 'agent-browser open https://github.com' would be blocked because //github.com was treated as an absolute file path outside the working directory. The fix adds a check to skip any path match that starts with '//', as these are URL path components, not file system paths. Fixes sipeed#1203 * fix: handle file:// URIs correctly in safety guard The previous fix skipped all paths starting with '//', which incorrectly also skipped file:// URIs that could escape the workspace sandbox. Changes: - Only skip '//' paths when preceded by web URL schemes (http:, https:, ftp:, etc.) - file:// URIs are now properly checked against workspace boundaries - Added TestShellTool_FileURISandboxing to verify the fix Fixes security issue raised by @alexhoshina in PR sipeed#1254 * style: fix gofumpt formatting * fix(safety-guard): use exact match position to prevent URL exemption bypass Using strings.Index(cmd, raw) always returned the first occurrence of the matched substring, allowing a bypass where the same //path appeared both inside a URL and as a standalone shell path (e.g. echo https://etc/passwd && cat //etc/passwd would skip the second match). Switch to FindAllStringIndex so each match is evaluated at its actual position in the command string. Adds TestShellTool_URLBypassPrevented to cover the exploit scenario.
Problem
The safety guard was incorrectly blocking commands containing URLs. For example,
agent-browser open https://gitlite.zycloud.tkwould be blocked with the error:Root Cause
The
absolutePathPatternregex matches absolute file paths in commands. When parsing a URL likehttps://github.com, the regex captures//gitlite.zycloud.tkas a match (the path portion afterhttps:). This was then treated as an absolute file path and blocked because it's outside the working directory.Fix
Added a check to skip any path match that starts with
//, as these are URL path components, not file system paths.Changes
guardCommandinpkg/tools/shell.goto skip URL path componentsTestShellTool_URLsNotBlockedto verify the fixFixes #1203