- VERSION file as authoritative version source - export.mjs reads VERSION with package.json fallback - bw-ota.ps1 DryRun mode for safe testing - auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
49 lines
1.6 KiB
JavaScript
49 lines
1.6 KiB
JavaScript
#!/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');
|