diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 2889074f..c66c6489 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -2,3 +2,7 @@ **Vulnerability:** Hardcoded API key ("ippoc-secret-key") used as default in `src/cortex/cortex/server.py`. **Learning:** Default configurations for development often make their way into production or expose systems during testing if not explicitly overridden. The system relied on a specific hardcoded string for default auth, which is a Critical vulnerability (CWE-798). **Prevention:** Never provide a hardcoded default for secrets. If a secret is missing, either generate a secure random one at runtime (fail-safe) or refuse to start (fail-secure). +## 2024-06-25 - [Command Injection in Thalamus Reflex Action] +**Vulnerability:** Unsanitized `signal.payload.pid` was concatenated directly into a `cp.exec` call for `renice` in `thalamus.ts`. +**Learning:** Even internal event payloads like `pid` must be treated as untrusted input. `child_process.exec` passes strings to a shell, allowing arbitrary command injection if the payload contains characters like `;` or `&&`. +**Prevention:** Always use `child_process.execFile` or `spawn` with parameterized arguments instead of `exec` with string concatenation. Additionally, when refactoring to `execFile`, always provide an error callback to avoid unhandled spawn errors crashing the process. diff --git a/infra/src/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts b/infra/src/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts index 2ddb081e..1b7d23ad 100644 --- a/infra/src/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts +++ b/infra/src/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts @@ -76,7 +76,12 @@ export class Thalamus { // Requires permissions, but this is the intent // In a real env, we might wrap this in a sudo-helper or just log it if permission denied import("child_process").then(cp => { - cp.exec(`renice +10 -p ${signal.payload.pid}`); + // Security Fix: Use execFile to prevent command injection + // Sanitize pid by ensuring it's treated as an argument string + const pidStr = String(signal.payload.pid); + cp.execFile('renice', ['+10', '-p', pidStr], (error) => { + if (error) console.error("Renice failed:", error); + }); }); return `REFLEX: Throttled process ${signal.payload.pid} (renice +10)`; } catch (e) { diff --git a/src/cortex/cortex/openclaw-cortex/openclaw-cortex/src/agents/thalamus.ts b/src/cortex/cortex/openclaw-cortex/openclaw-cortex/src/agents/thalamus.ts index 2ddb081e..1b7d23ad 100644 --- a/src/cortex/cortex/openclaw-cortex/openclaw-cortex/src/agents/thalamus.ts +++ b/src/cortex/cortex/openclaw-cortex/openclaw-cortex/src/agents/thalamus.ts @@ -76,7 +76,12 @@ export class Thalamus { // Requires permissions, but this is the intent // In a real env, we might wrap this in a sudo-helper or just log it if permission denied import("child_process").then(cp => { - cp.exec(`renice +10 -p ${signal.payload.pid}`); + // Security Fix: Use execFile to prevent command injection + // Sanitize pid by ensuring it's treated as an argument string + const pidStr = String(signal.payload.pid); + cp.execFile('renice', ['+10', '-p', pidStr], (error) => { + if (error) console.error("Renice failed:", error); + }); }); return `REFLEX: Throttled process ${signal.payload.pid} (renice +10)`; } catch (e) { diff --git a/src/ippoc/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts b/src/ippoc/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts index 2ddb081e..1b7d23ad 100644 --- a/src/ippoc/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts +++ b/src/ippoc/cortex/cortex/openclaw-cortex/src/agents/thalamus.ts @@ -76,7 +76,12 @@ export class Thalamus { // Requires permissions, but this is the intent // In a real env, we might wrap this in a sudo-helper or just log it if permission denied import("child_process").then(cp => { - cp.exec(`renice +10 -p ${signal.payload.pid}`); + // Security Fix: Use execFile to prevent command injection + // Sanitize pid by ensuring it's treated as an argument string + const pidStr = String(signal.payload.pid); + cp.execFile('renice', ['+10', '-p', pidStr], (error) => { + if (error) console.error("Renice failed:", error); + }); }); return `REFLEX: Throttled process ${signal.payload.pid} (renice +10)`; } catch (e) {