示例说明
日志泄漏密钥是高频安全事故:一次带授权头的错误日志就足以把生产凭证送进日志平台。Pino 的 redact 在序列化阶段生效,被命中的路径会被替换,性能开销极小。路径语法支持点分嵌套、方括号键名与星号通配,能覆盖常见凭证字段位置。
技术要点
- 点分路径精确命中嵌套字段
- 星号通配匹配任意层级的 token 字段
- censor 函数可保留长度信息辅助排障
代码解读
paths 同时列出请求头授权信息、API key、密码与通配形式的 token 字段;censor 用函数生成带原始长度的占位值,安全的同时保留长度特征用于格式排障。第二行日志演示 password 与任意嵌套深度下的 token 都会被拦截替换,其余字段正常输出。
使用建议
脱敏名单应纳入安全评审流程,新增字段同步维护。censor 输出不要包含任何原值片段。更彻底的做法是在源头就避免把凭证放进日志对象,redact 是最后防线。
代码示例
import { pino } from 'pino';
const logger = pino({
redact: {
paths: [
'req.headers.authorization',
'req.headers["x-api-key"]',
'password',
'*.token',
'user.credentials.*',
],
censor: (value) => (typeof value === 'string' ? '[redacted:' + value.length + ']' : '[redacted]'),
},
});
const req = {
id: 'req-91',
headers: { authorization: 'Bearer eyJhbGciOi', 'x-api-key': 'sk-live-9f2' },
};
logger.info({ req, user: { token: 'abc123', name: 'ada' } }, 'authenticated request');
logger.info({ password: 'hunter2', nested: { token: 'zzz' } }, 'form submitted');