Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions tools/peer-call/grok.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
// 1 — invocation error (bad arguments, cursor-agent missing, etc.)
// 2 — Grok returned a non-zero exit (response captured to stderr)

import { readFileSync, statSync } from "node:fs";
import { closeSync, openSync, readSync, statSync } from "node:fs";
import { spawnSync } from "node:child_process";

const SPAWN_MAX_BUFFER = 64 * 1024 * 1024;
Expand Down Expand Up @@ -157,23 +157,44 @@
}

function readHead(path: string, bytes: number): string {
// Read only the first `bytes` bytes (matches bash `head -c`).
// readFileSync would load the entire file before slicing — regression
// for large artifacts (logs, dumps) per Codex P1 on #898 (gemini.ts).
if (!isRegularFile(path)) return "";
const buf = readFileSync(path);
return buf.subarray(0, bytes).toString("utf8");
const buf = Buffer.alloc(bytes);
let fd: number | undefined;
try {
fd = openSync(path, "r");
const n = readSync(fd, buf, 0, bytes, 0);
return buf.subarray(0, n).toString("utf8");
} catch {
return "";
} finally {
if (fd !== undefined) closeSync(fd);
}
}

function runContextCmd(contextCmd: string): string {
// Bash uses `eval "$context_cmd" 2>&1 | head -c 20000`. Match that
// shape: shell -c so user-supplied compound commands work, capture
// both stdout + stderr, truncate to CTX_HEAD_BYTES. User intentionally
// supplies the shell command (per --context-cmd contract); same
// security posture as the bash original's `eval`.
const result = spawnSync("/bin/sh", ["-c", contextCmd], {
// shape end-to-end: pipe through `head -c <N>` so the shell pipeline
// short-circuits at the truncation boundary instead of buffering the
// full output up to SPAWN_MAX_BUFFER (Codex P2 on #898 — high-volume
// commands like wide `git diff` would otherwise block much longer
// and use much more memory than the bash original).
// User intentionally supplies the shell command (per --context-cmd
// contract); same security posture as the bash original's `eval`.
const wrapped = `(${contextCmd}) 2>&1 | head -c ${String(CTX_HEAD_BYTES)}`;
const result = spawnSync("/bin/sh", ["-c", wrapped], {
encoding: "utf8",
maxBuffer: SPAWN_MAX_BUFFER,
});

Check warning

Code scanning / CodeQL

Indirect uncontrolled command line Medium

This command depends on an unsanitized
command-line argument
.
const combined = `${result.stdout}${result.stderr}`;
return combined.slice(0, CTX_HEAD_BYTES);
// Concatenate stdout + stderr: stdout carries the command output
// truncated by `head -c`; stderr carries shell parse errors (e.g.,
// syntax errors in contextCmd) which fall OUTSIDE the `( ... ) 2>&1`
// redirection. Per Codex P2 + Copilot on #899 / #898 the parse-error
// diagnostic must reach the prompt or the user sees an empty context
// block on a malformed cmd.
return `${result.stdout}${result.stderr}`.slice(0, CTX_HEAD_BYTES);
}

const PREAMBLE = `You are Grok, invoked as a peer reviewer by Otto (Claude Opus 4.7
Expand Down
Loading