fix(security): prevent workspace PATH injection via service env and trash helpers#73264
Conversation
Greptile SummaryThis PR removes the external Confidence Score: 5/5This PR is safe to merge — the security fixes are correct, prior review findings have been addressed, and the new implementation is well-tested. No P0 or P1 issues remain. The workspace-derived PATH filtering logic correctly handles normalization, /proc/self/cwd prefix matching, symlink resolution via realpathSync.native, and the cwd === HOME exception. The movePathToDestination helper correctly handles EXDEV cross-device errors, TOCTOU collision codes, and the retry loop preserves the timestamp. All previously flagged issues were addressed in the follow-up commit. No files require special attention. Reviews (2): Last reviewed commit: "fix: address review-pr skill feedback" | Re-trigger Greptile |
|
@greptile review |
|
Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve. Keep this PR open. The cleanup policy blocks automated closure because the provided GitHub context lists the author association as Best possible solution: Keep this PR open for explicit maintainer/security review. If accepted, land this PR or an equivalent focused patch that removes PATH-resolved What I checked:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against b79e617ad12c. |
|
Addressed in Quoted comment from @aisle-research-bot:
|
|
Addressed in Quoted comment from @clawsweeper:
|
|
Addressed in Quoted comment from @aisle-research-bot:
|
|
Addressed in Quoted comment from @clawsweeper:
|
e330db4 to
e5e3a27
Compare
…rash helpers (openclaw#73264) * fix: address issue * fix: address PR review feedback * fix: address review-pr skill feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address build feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
…rash helpers (openclaw#73264) * fix: address issue * fix: address PR review feedback * fix: address review-pr skill feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address build feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
…rash helpers (openclaw#73264) * fix: address issue * fix: address PR review feedback * fix: address review-pr skill feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address build feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
…rash helpers (openclaw#73264) * fix: address issue * fix: address PR review feedback * fix: address review-pr skill feedback * fix: address PR review feedback * fix: address PR review feedback * fix: address build feedback * fix: address PR review feedback * docs: add changelog entry for PR merge
26194 drift commits, 222 flagged (security/regression keywords). Notable: XSS fix (openclaw#83104), PATH injection (openclaw#73264), npm_execpath injection (openclaw#73262), implicit tool grant fix (openclaw#75055), payment credential redaction (openclaw#75230), heartbeat regression (openclaw#88970).
Summary
PNPM_HOME,NPM_CONFIG_PREFIX,BUN_INSTALL,VOLTA_HOME,ASDF_DATA_DIR,NIX_PROFILES) could inject attacker-owned bin directories into the persisted gateway service PATH. A subsequent call tomovePathToTrash()resolved and executed a baretrashbinary from that PATH, enabling arbitrary local code execution during admin maintenance actions (e.g. agent deletion).movePathToTrash()in bothextensions/browser/src/browser/trash.tsandsrc/plugin-sdk/browser-maintenance.tsnow moves files directly to~/.Trashusingnode:fs+node:pathwithout invoking any external PATH-resolved command. (2)service-env.tsanddaemon-install-helpers.tsnow filter out workspace-derived directories (literal/proc/self/cwd/…and any real path resolving inside the installcwd) before they can become durable service PATH entries.~/.Trashfallback behaviour is now the only code path (behaviorally equivalent on macOS where~/.Trashis the native Trash folder; unchanged on Linux).Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
mergeServicePathindaemon-install-helpers.tspreserved existing PATH segments that passed only a tmp-dir filter, allowing workspace-relative or/proc/self/cwd-rooted entries to survive into the persisted service environment.movePathToTrash()then resolved thetrashbinary from that poisoned PATH.PNPM_HOME, etc.) are legitimately set by user toolchains but should never become durable service PATH entries when they point into the install workspace.Regression Test Plan (if applicable)
src/daemon/service-env.test.ts— new cases assert workspace-derived dirs are excluded and that thecwd === HOMEexception is preserved.src/commands/daemon-install-helpers.test.ts— updated PATH input now includes/proc/self/cwd/evil-binand${process.cwd()}/evil-bin; asserts they are stripped from merged PATH.extensions/browser/src/browser/trash.test.tsandsrc/plugin-sdk/browser-maintenance.test.ts— assertrunExecis never called and files land in~/.Trashvia directfscalls.movePathToTrash()never forks an external process.User-visible / Behavior Changes
movePathToTrash()now always returns the destination path inside~/.Trash(previously returned the original path when the externaltrashcommand succeeded). This is internal to admin cleanup paths and not exposed to end users.Diagram (if applicable)
Security Impact (required)
runExec("trash", ...)removed; file-system-only path used instead. Risk: none; mitigation: directnode:fsrename cannot be hijacked via PATH.Repro + Verification
Environment
Steps
PNPM_HOME=/proc/self/cwd/evil-pnpm-homeand place a faketrashbinary atevil-pnpm-home/trash.movePathToTrash()(e.g. via agent deletion).Expected
trashbinary is never resolved or executed; file is moved to~/.Trashdirectly./proc/self/cwd/evil-pnpm-homedoes not appear in the persisted service PATH.Actual (before fix)
trashbinary executed.Evidence
runExecsuppression and PATH filtering for/proc/self/cwd/…and${process.cwd()}/…entries.Human Verification (required)
isWorkspaceDerivedPath,normalizePreservedPathSegment, and bothmovePathToTrashimplementations.cwd === HOMEexception (safe toolchain roots under HOME are kept); non-existent legacy PATH entries handled byrealpathSynctry/catch;existsSynccollision path in trash helpers.Review Conversations
Compatibility / Migration
Risks and Mitigations
movePathToTrash()no longer invokes the systemtrashcommand, so files moved to~/.Trashon macOS bypass any Finder Trash hooks or third-party trash integrations.~/.Trashis the native macOS Trash directory; files are still recoverable via Finder. On Linux the external command was a no-op fallback, so behavior is unchanged.