99 lines
3.3 KiB
JavaScript
99 lines
3.3 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* sensitive-paths.json 扩展补丁 — 2026-04-25
|
||
|
|
*
|
||
|
|
* 目标: 将 ai-delivery-pipeline/ 三区目录纳入敏感路径保护
|
||
|
|
* - staging/ 防止 Edit/Write 直接写入 (应通过 pipeline 流转)
|
||
|
|
* - quarantine/ 防止恶意隔离样本被读回 (red-team-attacker 攻击 3)
|
||
|
|
* - delivery/ 防止直接覆盖交付区 (绕过验证管道)
|
||
|
|
*
|
||
|
|
* 依据: red-team-attacker 攻击 3 [HIGH 75%] "Quarantine 恶意代码图书馆"
|
||
|
|
* red-team-logic C2 [CRITICAL] "用户编辑 quarantine 导致递归 staging"
|
||
|
|
*
|
||
|
|
* 设计:
|
||
|
|
* - 新增 3 条 regex 规则, 匹配 .claude/ai-delivery-pipeline/{staging,quarantine,delivery}/
|
||
|
|
* - _version bump: v3.9-s1 → v3.10-s1-delivery-pipeline
|
||
|
|
*
|
||
|
|
* 幂等: 若规则已存在 (按 reason 标识) 则跳过。
|
||
|
|
* 原子: tmp + rename。
|
||
|
|
* 回滚: .bak 保留。
|
||
|
|
* 后续: 补丁完成后需 `node scripts/compile-rules.js` 刷新 rules-compiled.json。
|
||
|
|
*/
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
const { execSync } = require('child_process');
|
||
|
|
|
||
|
|
const TARGET = path.join(__dirname, '..', '..', 'hooks', 'rules', 'sensitive-paths.json');
|
||
|
|
const COMPILE_RULES = path.join(__dirname, '..', 'compile-rules.js');
|
||
|
|
|
||
|
|
const NEW_RULES = [
|
||
|
|
{
|
||
|
|
regex: '[\\\\/]\\.claude[\\\\/]ai-delivery-pipeline[\\\\/]staging[\\\\/]',
|
||
|
|
flags: 'i',
|
||
|
|
reason: 'AI 交付流水线 staging 区 (应通过 pipeline 流转, 禁止直写)',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
regex: '[\\\\/]\\.claude[\\\\/]ai-delivery-pipeline[\\\\/]quarantine[\\\\/]',
|
||
|
|
flags: 'i',
|
||
|
|
reason: 'AI 交付流水线 quarantine 区 (防恶意样本读回 / red-team 攻击 3)',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
regex: '[\\\\/]\\.claude[\\\\/]ai-delivery-pipeline[\\\\/]delivery[\\\\/]',
|
||
|
|
flags: 'i',
|
||
|
|
reason: 'AI 交付流水线 delivery 区 (禁绕过验证管道直覆盖)',
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
const NEW_VERSION = 'v3.10-s1-delivery-pipeline';
|
||
|
|
|
||
|
|
function main() {
|
||
|
|
if (!fs.existsSync(TARGET)) {
|
||
|
|
console.error('[patch-spaths] 目标不存在:', TARGET);
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
const raw = fs.readFileSync(TARGET, 'utf8');
|
||
|
|
const json = JSON.parse(raw);
|
||
|
|
|
||
|
|
const existingReasons = new Set(json.patterns.map(p => p.reason));
|
||
|
|
const toAdd = NEW_RULES.filter(r => !existingReasons.has(r.reason));
|
||
|
|
|
||
|
|
if (toAdd.length === 0) {
|
||
|
|
console.log('[patch-spaths] 规则已存在, 跳过');
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 备份
|
||
|
|
const bakPath = TARGET + '.bak.delivery-pipeline.' + new Date().toISOString().replace(/[:.]/g, '-');
|
||
|
|
fs.writeFileSync(bakPath, raw, 'utf8');
|
||
|
|
|
||
|
|
json._version = NEW_VERSION;
|
||
|
|
json.patterns.push(...toAdd);
|
||
|
|
|
||
|
|
// 原子写
|
||
|
|
const newRaw = JSON.stringify(json, null, 2) + '\n';
|
||
|
|
const tmp = TARGET + '.tmp.' + process.pid;
|
||
|
|
fs.writeFileSync(tmp, newRaw, 'utf8');
|
||
|
|
fs.renameSync(tmp, TARGET);
|
||
|
|
|
||
|
|
console.log('[patch-spaths] 追加', toAdd.length, '条规则:');
|
||
|
|
toAdd.forEach(r => console.log(' +', r.reason));
|
||
|
|
console.log('[patch-spaths] _version →', NEW_VERSION);
|
||
|
|
console.log('[patch-spaths] 备份:', path.basename(bakPath));
|
||
|
|
|
||
|
|
// 刷新编译规则缓存
|
||
|
|
if (fs.existsSync(COMPILE_RULES)) {
|
||
|
|
try {
|
||
|
|
const out = execSync('node "' + COMPILE_RULES + '"', { encoding: 'utf8' });
|
||
|
|
console.log('[patch-spaths] rules-compiled.json 已刷新');
|
||
|
|
if (out.trim()) console.log(out.trim().split('\n').slice(-3).join('\n'));
|
||
|
|
} catch (e) {
|
||
|
|
console.error('[patch-spaths] compile-rules 失败:', e.message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
main();
|