60 lines
2.4 KiB
JavaScript
60 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* 共享日志脱敏模块 (v5.9)
|
||
*
|
||
* 统一所有组件的敏感信息过滤规则,避免规则分散导致不一致。
|
||
* 被 route-interceptor.js 和 activity-logger.js 共同引用。
|
||
*/
|
||
|
||
/**
|
||
* 日志脱敏: 移除疑似敏感信息
|
||
* @param {string} text - 原始文本
|
||
* @returns {string} 脱敏后文本
|
||
*/
|
||
function sanitize(text) {
|
||
if (!text || typeof text !== 'string') return text || '';
|
||
return text
|
||
// 键值对形式: key=xxx, token: xxx, password=xxx 等
|
||
.replace(/(?:key|token|password|secret|credential|apikey|api_key|auth|passwd)[\s]*[=:]\s*\S{6,}/gi, (m) => {
|
||
const sep = m.indexOf('=') !== -1 ? '=' : ':';
|
||
const prefix = m.slice(0, m.indexOf(sep) + 1);
|
||
return prefix + ' [REDACTED]';
|
||
})
|
||
// 已知 token 前缀: sk-, ghp_, Bearer 等 (后跟 >=10 字符)
|
||
.replace(/\b(?:sk-|ghp_|gho_|github_pat_|xoxb-|xoxp-|Bearer\s+)\S{10,}/g, '[REDACTED_TOKEN]')
|
||
// AWS Access Key (AKIA 开头 20 字符)
|
||
.replace(/\bAKIA[A-Z0-9]{16}\b/g, '[REDACTED_TOKEN]')
|
||
// JWT token (eyJ 开头的 Base64url 段)
|
||
.replace(/\beyJ[A-Za-z0-9_-]{20,}(?:\.[A-Za-z0-9_-]+)*/g, '[REDACTED_TOKEN]')
|
||
// 疑似 Base64 编码密钥 (长度 >= 40)
|
||
.replace(/\b[A-Za-z0-9+/]{64,}={0,2}\b/g, (m) => { // V07 修复: 阈值 40→64,减少 Git SHA/路径误杀
|
||
if (/^[A-Za-z0-9+/]+={0,2}$/.test(m)) return '[REDACTED_B64]';
|
||
return m;
|
||
})
|
||
// UUID 格式 Token (当作为 TOKEN/KEY/SECRET 等的值出现时)
|
||
.replace(/(?:TOKEN|KEY|SECRET|CREDENTIAL|PASSWORD|API_KEY)[\s]*[=:]\s*[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, (m) => {
|
||
const sep = m.indexOf('=') !== -1 ? '=' : ':';
|
||
const prefix = m.slice(0, m.indexOf(sep) + 1);
|
||
return prefix + ' [REDACTED_UUID]';
|
||
});
|
||
}
|
||
|
||
if (typeof module !== 'undefined') {
|
||
|
||
|
||
// #12: 磁盘满降级日志 — appendFileSync 失败时 fallback 到 stderr
|
||
function safeAppendLog(filePath, jsonData) {
|
||
try {
|
||
const dir = require('path').dirname(filePath);
|
||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||
fs.appendFileSync(filePath, JSON.stringify(jsonData) + '\n');
|
||
} catch (e) {
|
||
// 磁盘满或权限错误时输出到 stderr (至少留下审计痕迹)
|
||
try { process.stderr.write('[LOG-FALLBACK] ' + JSON.stringify(jsonData) + '\n'); } catch {}
|
||
}
|
||
}
|
||
|
||
module.exports = {
|
||
safeAppendLog, sanitize };
|
||
}
|