bookworm-smart-assistant/hooks/lib/security-log.js

45 lines
1.4 KiB
JavaScript
Raw Normal View History

/**
* 共享安全事件日志模块 (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 };