Session infrastructure: OpenRouter + tree-split reducer + observer→LLM Team + scrum_applier #11

Merged
profit merged 118 commits from scrum/auto-apply-19814 into main 2026-04-27 15:55:24 +00:00
Showing only changes of commit 2d9cb128bf - Show all commits

View File

@ -364,7 +364,21 @@ async function computeGrounding(findings: Finding[]): Promise<{ total: number; v
const [, relpath, lineStr] = m; const [, relpath, lineStr] = m;
const line = Number(lineStr); const line = Number(lineStr);
if (!line || !relpath) return false; if (!line || !relpath) return false;
const abs = relpath.startsWith("/") ? relpath : resolve(REPO_ROOT, relpath);
// Path-traversal guard (caught 2026-04-27 by Kimi self-audit on
// dd77632). A model output emitting `../../../etc/passwd:1` would
// otherwise resolve outside REPO_ROOT and we'd readFile() a system
// file. Resolve, then verify the absolute path is anchored under
// REPO_ROOT — refuse anything that escapes (relative ".." traversal
// OR an absolute path that doesn't start with REPO_ROOT). Existing
// grounding-citation conventions all use repo-relative paths, so
// this rejection is safe in practice.
const abs = resolve(REPO_ROOT, relpath);
if (!abs.startsWith(REPO_ROOT + "/") && abs !== REPO_ROOT) {
f.evidence.push(`[grounding: path escapes repo root, refusing]`);
return false;
}
if (!existsSync(abs)) { if (!existsSync(abs)) {
f.evidence.push("[grounding: file not found]"); f.evidence.push("[grounding: file not found]");
return false; return false;