Fix shell injection — use tee with stdin instead of echo interpolation
This commit is contained in:
@@ -10,6 +10,13 @@ import {
|
||||
import { join } from "node:path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { CONFIG } from "./config.js";
|
||||
|
||||
const SSH_OPTS = [
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "ConnectTimeout=5",
|
||||
"-i", CONFIG.sshKeyPath,
|
||||
];
|
||||
import {
|
||||
allocateIp,
|
||||
releaseIp,
|
||||
@@ -103,7 +110,7 @@ function injectAgentConfig(
|
||||
{ stdio: "pipe" }
|
||||
);
|
||||
|
||||
// Write config
|
||||
// Write config (via stdin to avoid shell injection)
|
||||
const configJson = JSON.stringify({
|
||||
nick: config.nick,
|
||||
model: config.model,
|
||||
@@ -112,26 +119,18 @@ function injectAgentConfig(
|
||||
port: 6667,
|
||||
ollama_url: "http://172.16.0.1:11434",
|
||||
});
|
||||
execFileSync(
|
||||
"sudo",
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
`echo '${configJson}' > ${join(mountPoint, "etc/agent/config.json")}`,
|
||||
],
|
||||
{ stdio: "pipe" }
|
||||
);
|
||||
const configPath = join(mountPoint, "etc/agent/config.json");
|
||||
execFileSync("sudo", ["tee", configPath], {
|
||||
input: configJson,
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
// Write persona
|
||||
execFileSync(
|
||||
"sudo",
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
`cat > ${join(mountPoint, "etc/agent/persona.md")} << 'PERSONA_EOF'\n${persona}\nPERSONA_EOF`,
|
||||
],
|
||||
{ stdio: "pipe" }
|
||||
);
|
||||
// Write persona (via stdin to avoid shell injection)
|
||||
const personaPath = join(mountPoint, "etc/agent/persona.md");
|
||||
execFileSync("sudo", ["tee", personaPath], {
|
||||
input: persona,
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
// Inject SSH key for debugging access
|
||||
execFileSync("sudo", ["mkdir", "-p", join(mountPoint, "root/.ssh")], {
|
||||
@@ -301,14 +300,7 @@ export async function stopAgent(name: string) {
|
||||
try {
|
||||
execFileSync(
|
||||
"ssh",
|
||||
[
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "ConnectTimeout=3",
|
||||
"-i", CONFIG.sshKeyPath,
|
||||
`root@${info.ip}`,
|
||||
"killall python3 2>/dev/null; sleep 1",
|
||||
],
|
||||
[...SSH_OPTS, `root@${info.ip}`, "killall python3 2>/dev/null; sleep 1"],
|
||||
{ stdio: "pipe", timeout: 5_000 }
|
||||
);
|
||||
} catch {
|
||||
@@ -405,13 +397,6 @@ export async function reloadAgent(
|
||||
}
|
||||
if (updates.trigger) configUpdates.trigger = updates.trigger;
|
||||
|
||||
// Write updated config as a temp file on the VM via SSH
|
||||
const sshOpts = [
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-o", "ConnectTimeout=5",
|
||||
"-i", CONFIG.sshKeyPath,
|
||||
];
|
||||
const sshTarget = `root@${info.ip}`;
|
||||
|
||||
try {
|
||||
@@ -419,7 +404,7 @@ export async function reloadAgent(
|
||||
// Read current config from VM
|
||||
const currentRaw = execFileSync(
|
||||
"ssh",
|
||||
[...sshOpts, sshTarget, "cat /etc/agent/config.json"],
|
||||
[...SSH_OPTS, sshTarget, "cat /etc/agent/config.json"],
|
||||
{ encoding: "utf-8", timeout: 10_000 }
|
||||
);
|
||||
const current = JSON.parse(currentRaw);
|
||||
@@ -429,7 +414,7 @@ export async function reloadAgent(
|
||||
// Write back via stdin
|
||||
execFileSync(
|
||||
"ssh",
|
||||
[...sshOpts, sshTarget, `cat > /etc/agent/config.json`],
|
||||
[...SSH_OPTS, sshTarget, `cat > /etc/agent/config.json`],
|
||||
{ input: newConfig, timeout: 10_000 }
|
||||
);
|
||||
}
|
||||
@@ -437,7 +422,7 @@ export async function reloadAgent(
|
||||
if (updates.persona) {
|
||||
execFileSync(
|
||||
"ssh",
|
||||
[...sshOpts, sshTarget, `cat > /etc/agent/persona.md`],
|
||||
[...SSH_OPTS, sshTarget, `cat > /etc/agent/persona.md`],
|
||||
{ input: updates.persona, timeout: 10_000 }
|
||||
);
|
||||
}
|
||||
@@ -445,7 +430,7 @@ export async function reloadAgent(
|
||||
// Signal agent to reload
|
||||
execFileSync(
|
||||
"ssh",
|
||||
[...sshOpts, sshTarget, "killall -HUP python3"],
|
||||
[...SSH_OPTS, sshTarget, "killall -HUP python3"],
|
||||
{ stdio: "pipe", timeout: 10_000 }
|
||||
);
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user