#!/usr/bin/env node /** * patch-x11-transcript-path-validation.js * context-pressure-monitor.js findTranscript() 加路径前缀校验 + session_id 防路径穿越 * * 幂等: SENTINEL 标记 */ 'use strict'; const fs = require('fs'); const path = require('path'); const SENTINEL = '[PATCH-X11-PATH-VALIDATION]'; const TARGET = path.join(__dirname, '..', '..', 'hooks', 'context-pressure-monitor.js'); if (!fs.existsSync(TARGET)) { console.log('SKIP: target not found'); process.exit(0); } let src = fs.readFileSync(TARGET, 'utf8').replace(/\r\n/g, '\n'); if (src.includes(SENTINEL)) { console.log('SKIP: already patched'); process.exit(0); } const oldFunc = `function findTranscript(hookData) { if (hookData.transcript_path && fs.existsSync(hookData.transcript_path)) { return hookData.transcript_path; } const sid = hookData.session_id; if (!sid || !fs.existsSync(PROJECTS_DIR)) return null;`; const newFunc = `function findTranscript(hookData) { // ${SENTINEL} if (hookData.transcript_path) { const resolved = path.resolve(hookData.transcript_path); if (resolved.startsWith(CLAUDE_ROOT) && fs.existsSync(resolved)) { return resolved; } } const sid = hookData.session_id; if (!sid || /[\\/\\\\]/.test(sid) || !fs.existsSync(PROJECTS_DIR)) return null;`; if (!src.includes(oldFunc)) { console.error('FAIL: old findTranscript not found'); process.exit(1); } src = src.replace(oldFunc, newFunc); const tmp = TARGET + '.tmp.' + process.pid; fs.writeFileSync(tmp, src, 'utf8'); fs.renameSync(tmp, TARGET); console.log('OK: X11 transcript path validation + session_id sanitization patched');