fix(#1858): address code+security review findings

- restructure _loadFlatCommandsGsdManifest try/catch to wrap read+parse+set
  together (mirrors loadSkillsManifest exactly), so a thrown parser degrades
  both keys to [] — closes the latent catch-scope parity drift [Nit-1]
- add boundary test: gsd-.md (empty stem) skipped, gsd-x.md single-char stem
  kept (slice(4,-3) boundary) [Low-1]
- add unreadable-file test (POSIX-gated): both keys degrade to [] [Low-2]
- strengthen parity test to also compare requires + _calls_agents_ VALUES,
  not just the stem set [Nit-2]

Both orthogonal reviews returned APPROVE with no Critical/High findings.
Security review confirmed no new trust-boundary crossing, prototype-pollution
immune (Map/Set throughout), and symlink/path-traversal surface identical to
the pre-existing nested loader (not a regression).
This commit is contained in:
Tom Boucher
2026-07-06 21:35:24 -04:00
parent e3d053619c
commit 2c853822a1
2 changed files with 59 additions and 6 deletions

View File

@@ -416,15 +416,19 @@ function _loadFlatCommandsGsdManifest(commandsParentDir: string): Map<string, st
// Strip 'gsd-' prefix (4 chars) and '.md' suffix (3 chars) → stem.
const stem = entry.name.slice(4, -3);
if (!stem) continue;
let content = '';
// Mirror loadSkillsManifest's try/catch structure exactly: wrap read +
// parse + set together so an unreadable file OR a thrown parser degrades
// both keys to [] (parity; closes the latent catch-scope drift a reviewer
// flagged — both parsers are non-throwing today, but the structural
// match future-proofs the "identical Map shape" contract).
try {
content = fs.readFileSync(path.join(commandsParentDir, entry.name), 'utf8');
const content = fs.readFileSync(path.join(commandsParentDir, entry.name), 'utf8');
manifest.set(stem, parseRequires(content));
manifest.set(`_calls_agents_${stem}`, parseCallsAgents(content));
} catch {
// Unreadable file — register with empty deps + agents (parity with
// loadSkillsManifest's readFileSync catch branch).
manifest.set(stem, []);
manifest.set(`_calls_agents_${stem}`, []);
}
manifest.set(stem, content ? parseRequires(content) : []);
manifest.set(`_calls_agents_${stem}`, content ? parseCallsAgents(content) : []);
}
return manifest;
}