From be76707452de3e61eb8a3422b636a80012e1acc6 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Mon, 11 May 2026 22:22:26 -0300 Subject: [PATCH] fix(cliRuntime): resolve TDZ for isWindows in devin config via lazy getter, add spawn metachar guard Co-Authored-By: Claude Sonnet 4.6 --- src/shared/services/cliRuntime.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/shared/services/cliRuntime.ts b/src/shared/services/cliRuntime.ts index 8dec6100f6..db867849cc 100644 --- a/src/shared/services/cliRuntime.ts +++ b/src/shared/services/cliRuntime.ts @@ -76,13 +76,15 @@ const CLI_TOOLS: Record = { paths: { // %APPDATA%\devin\config.json (Windows) // ~/.config/devin/config.json (Linux/macOS) - config: isWindows() - ? path.join( - process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), - "devin", - "config.json" - ) - : path.join(os.homedir(), ".config", "devin", "config.json"), + get config() { + return isWindows() + ? path.join( + process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), + "devin", + "config.json" + ) + : path.join(os.homedir(), ".config", "devin", "config.json"); + }, }, }, cline: { @@ -205,6 +207,13 @@ const runProcess = ( } = {} ): Promise => new Promise((resolve) => { + // Guard: reject commands with shell metacharacters — command comes from + // server-controlled env vars/config, not HTTP input, but belt-and-suspenders. + if (/[;&|`$<>\n\r]/.test(command)) { + resolve({ ok: false, stdout: "", stderr: "rejected: unsafe command path", exitCode: -1 }); + return; + } + let stdout = ""; let stderr = ""; let timedOut = false;