45 lines
1.4 KiB
JavaScript
45 lines
1.4 KiB
JavaScript
|
|
/**
|
|||
|
|
* 共享安全事件日志模块 (M14)
|
|||
|
|
*
|
|||
|
|
* 替代 5 个 hook 中各自实现的 logSecurityEvent 函数。
|
|||
|
|
* 统一日志格式、脱敏策略和文件写入逻辑。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
const { safeAppendJsonl } = require('./safe-append.js');
|
|||
|
|
|
|||
|
|
const CLAUDE_ROOT = require('./root.js');
|
|||
|
|
const DEBUG_DIR = path.join(CLAUDE_ROOT, 'debug');
|
|||
|
|
|
|||
|
|
// 脱敏函数(优先使用 sanitize.js)
|
|||
|
|
const _sanitize = (() => {
|
|||
|
|
try { return require('../../scripts/sanitize.js').sanitize; }
|
|||
|
|
catch { return (text) => (text || '').replace(/[A-Za-z0-9+/]{32,}/g, '[REDACTED]'); }
|
|||
|
|
})();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 写入安全事件日志
|
|||
|
|
* @param {string} decision - 决策类型 (deny/ask/allow/auto-fix/hook-tamper 等)
|
|||
|
|
* @param {string} hook - hook 名称
|
|||
|
|
* @param {string} reason - 原因描述
|
|||
|
|
* @param {string} [detail] - 详细信息(会被脱敏和截断)
|
|||
|
|
*/
|
|||
|
|
function logSecurityEvent(decision, hook, reason, detail) {
|
|||
|
|
try {
|
|||
|
|
if (!fs.existsSync(DEBUG_DIR)) fs.mkdirSync(DEBUG_DIR, { recursive: true });
|
|||
|
|
const dateStr = new Date().toISOString().slice(0, 10);
|
|||
|
|
const logFile = path.join(DEBUG_DIR, `security-${dateStr}.jsonl`);
|
|||
|
|
const entry = {
|
|||
|
|
ts: new Date().toISOString(),
|
|||
|
|
decision,
|
|||
|
|
hook,
|
|||
|
|
reason,
|
|||
|
|
detail: _sanitize((detail || '').slice(0, 200)),
|
|||
|
|
};
|
|||
|
|
safeAppendJsonl(logFile, entry);
|
|||
|
|
} catch {}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = { logSecurityEvent, _sanitize };
|