bash-json-guard.js 1.51 KB
/**
 * DevLoop · Bash inline-JSON guard 中间件
 *
 * 拦截 Coder/Tester/Integrator 通过 Bash 工具发送的<b>inline JSON</b> 命令
 * (CLAUDE.md L91-99 强约束)。挂到 Bash 工具的 preExecute 钩子里。
 *
 * 反例(禁): curl -d '{"k":"v"}' http://...
 * 正例:    echo '{"k":"v"}' > /tmp/x.json && curl -d @/tmp/x.json http://...
 *
 * 规格: docs/prd/newfunction/_spec/arch-tool-registry.md · §⑥
 */

// 检测 `-d '{...}'` `-d "{...}"` 或 `--data '{...}'` `--data-raw '{...}'`
const INLINE_JSON_PATTERNS = [
  /-d\s+(['"])\s*\{[\s\S]*?\}\s*\1/,
  /--data\s+(['"])\s*\{[\s\S]*?\}\s*\1/,
  /--data-raw\s+(['"])\s*\{[\s\S]*?\}\s*\1/,
  /--data-binary\s+(['"])\s*\{[\s\S]*?\}\s*\1/,
];

function jsonGuard(cmd) {
  if (typeof cmd !== 'string') return { ok: true };
  for (const re of INLINE_JSON_PATTERNS) {
    if (re.test(cmd)) {
      return {
        ok: false,
        reason: 'inline JSON in Bash command is forbidden (see CLAUDE.md L91-99). ' +
                'Use: echo \'{"k":"v"}\' > /tmp/x.json && curl -d @/tmp/x.json',
        matched_pattern: re.source,
      };
    }
  }
  return { ok: true };
}

/**
 * preExecute hook 注册形式(LemonBoss Bash 工具内部消费)
 */
const bashHooks = {
  preExecute: [
    (cmd) => {
      const r = jsonGuard(cmd);
      if (!r.ok) {
        const e = new Error(r.reason);
        e.code = 'JSON_GUARD_BLOCK';
        e.matched_pattern = r.matched_pattern;
        throw e;
      }
    },
  ],
};

module.exports = { jsonGuard, bashHooks, INLINE_JSON_PATTERNS };