Skip to content

fix: safety guard incorrectly blocks commands with URLs#1254

Merged
alexhoshina merged 4 commits intosipeed:mainfrom
hkc5:fix-safety-guard-url-blocking
Mar 13, 2026
Merged

fix: safety guard incorrectly blocks commands with URLs#1254
alexhoshina merged 4 commits intosipeed:mainfrom
hkc5:fix-safety-guard-url-blocking

Conversation

@hkc5
Copy link
Copy Markdown
Contributor

@hkc5 hkc5 commented Mar 8, 2026

Problem

The safety guard was incorrectly blocking commands containing URLs. For example, agent-browser open https://github.com would be blocked with the error:

Command blocked by safety guard (path outside working dir)

Root Cause

The absolutePathPattern regex matches absolute file paths in commands. When parsing a URL like https://github.com, the regex captures //github.com as a match (the path portion after https:). 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

  • Modified guardCommand in pkg/tools/shell.go to skip URL path components
  • Added test case TestShellTool_URLsNotBlocked to verify the fix

Fixes #1203

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
@hkc5
Copy link
Copy Markdown
Contributor Author

hkc5 commented Mar 9, 2026

@imguoguo

Copy link
Copy Markdown

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. No legitimate absolute filesystem path starts with // in normal usage
  2. 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.

@hkc5
Copy link
Copy Markdown
Contributor Author

hkc5 commented Mar 10, 2026

Thanks for the review Nicolas, I guess we need another reviewer
tagging from the CONTRIBUTING.md
@yinwm @alexhoshina @lxowalle @Zhaoyikaiii

Comment thread pkg/tools/shell.go Outdated
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
@alexhoshina
Copy link
Copy Markdown
Collaborator

make lint plz

Comment thread pkg/tools/shell.go Outdated
…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.
Comment thread pkg/tools/shell.go
Comment on lines +358 to +359
for _, scheme := range webSchemes {
if strings.HasSuffix(before, scheme) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: HTTPS:example.com will be blocked. This issue does not affect merging; it is merely a minor detail.

Comment thread pkg/tools/shell_test.go
Comment on lines +459 to +466
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",
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Real network requests may cause the exec tool to time out or slow down the CI.

@hkc5
Copy link
Copy Markdown
Contributor Author

hkc5 commented Mar 13, 2026

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!

@alexhoshina alexhoshina merged commit 6b72326 into sipeed:main Mar 13, 2026
4 checks passed
@Orgmar
Copy link
Copy Markdown
Contributor

Orgmar commented Mar 13, 2026

@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 support@sipeed.com with the subject [Join PicoClaw Dev Group] + your GitHub account and we'll send you the invite link!

dj-oyu pushed a commit to dj-oyu/picoclaw that referenced this pull request Mar 16, 2026
* 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.
neotty pushed a commit to neotty/picoclaw that referenced this pull request Mar 17, 2026
* 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.
j0904 pushed a commit to j0904/picoclaw that referenced this pull request Mar 22, 2026
* 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.
andressg79 pushed a commit to andressg79/picoclaw that referenced this pull request Mar 30, 2026
* 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.
ra1phdd pushed a commit to ra1phdd/picoclaw-pkg that referenced this pull request Apr 12, 2026
* 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: tool go Pull requests that update go code type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Safety guard incorrectly blocks commands containing URLs

4 participants