fix(webchat): reject remote-host file:// URLs in media embedding path [AI-assisted]#67293
fix(webchat): reject remote-host file:// URLs in media embedding path [AI-assisted]#67293pgondhi987 merged 4 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a security bypass in Confidence Score: 5/5Safe to merge — tightly scoped security hardening with no behavior change for legitimate local paths, consistent with existing policy in reply-media-paths.ts. All remaining findings are P2 or lower. The fix is minimal, uses the already-audited safeFileURLToPath helper, and is backed by a targeted test that confirms no filesystem access for the attack input. No logic changes outside the security boundary. No files require special attention. Reviews (1): Last reviewed commit: "fix: address issue" | Re-trigger Greptile |
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b429dfb3cf
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
… [AI-assisted] (openclaw#67293) * fix: address issue * fix: address PR review feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
… [AI-assisted] (openclaw#67293) * fix: address issue * fix: address PR review feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
Summary
resolveLocalMediaPathForEmbeddinginchat-webchat-media.tsused rawfileURLToPath()to resolvefile:URLs, skipping the host validation that already exists for normal reply media paths. Afile://attacker/share/probe.mp3-style URL could reachstatSync/readFileSync; on Windows it resolves to a UNC path and can trigger outbound SMB access.reply-media-paths.tsalready rejects hostfile://URLs). This was a concrete bypass of a defense-in-depth boundary, with elevated impact on Windows deployments.fileURLToPath()withsafeFileURLToPath()fromsrc/infra/local-file-access.ts(validates hostname is empty/localhost, rejects encoded separators, rejects Windows UNC paths). AddedassertNoWindowsNetworkPath()on the raw absolute-path branch to cover Windows UNC strings passed directly.file:///absolute/pathorfile://localhost/absolute/pathinputs. No changes to routing, tool-result promotion logic, or other media paths.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
resolveLocalMediaPathForEmbeddingcalledfileURLToPath()directly without checking the URL hostname, while the existingsafeFileURLToPath()helper (already used elsewhere) performs that validation.file://URLs in the webchat media embedding path.reply-media-paths.ts), so the weaker sink was reachable.Regression Test Plan (if applicable)
src/gateway/server-methods/chat-webchat-media.test.tsfile://attacker/share/probe.mp3returns zero audio blocks and never callsstatSyncorreadFileSync.buildWebchatAudioContentBlocksFromReplyPayloadswith the attack input and asserts no filesystem access occurs.User-visible / Behavior Changes
None. Legitimate local audio embedding is unaffected.
Diagram (if applicable)
Security Impact (required)
file://URLs onlyRepro + Verification
Environment
Steps
buildWebchatAudioContentBlocksFromReplyPayloadswithmediaUrl: "file://attacker/share/probe.mp3".fileURLToPathpasses through (or resolves to UNC on Windows);statSyncis called.safeFileURLToPaththrows on non-localhost hostname; function returns[].Expected
Actual (after fix)
statSyncandreadFileSyncspy assertions confirm no filesystem access.Evidence
drops tool-result file:// URLs with remote hosts before touching the filesysteminchat-webchat-media.test.tscovers the exact attack vector.Human Verification (required)
file://URL rejected before filesystem access; existing tests for legitimate local paths continue to pass.file://localhost/...still resolves correctly; oversized files still rejected via stat cap; non-audio extensions still filtered.Review Conversations
Compatibility / Migration
Risks and Mitigations
file://hostname/...URLs in webchat media (e.g., internal NFS mounts addressed via hostname).reply-media-paths.tspolicy already blocks it for normal replies, making this consistent rather than restrictive.