接口偶发超时,供应商让你提供一条请求日志。你找到时间、状态码、耗时和错误信息,准备直接粘贴到工单里,却发现同一条 JSON 还带着 Authorization、用户邮箱和内部账号 ID。
整条删掉,问题难以排查;把所有值改成 ***,文件也许仍然能解析,但接手的人看不出是 504 超时还是参数校验失败。
更合理的目标不是「清空日志」,而是制作一份范围尽可能小、保留必要诊断线索的副本。下面用合成数据走一遍流程,所有示例均不含真实客户信息或有效凭据。
1. 先确定要回答什么问题
如果要判断是不是上游超时,通常值得保留的是:请求方法、必要的路由信息、状态码、耗时、重试次数和错误码。用户的真实邮箱一般不能帮助回答这个问题。
但这不是固定白名单。路由也可能包含租户 ID;精确时间与少见事件组合起来,也可能识别某个人。因此,字段是否保留,要看接收方需要什么、组织允许分享什么。
尽量截取复现问题前后的最小时间窗口,不要把一天的日志打包发出去。原文件留在授权环境,只处理副本。
2. 优先清理能授予访问权限的内容
先检查 Token、Cookie、密码、API Key、数据库连接串和签名 URL,再处理邮箱、手机号、内部地址等信息。
不要只搜索 password。凭据可能藏在请求头、嵌套对象、数组、URL 参数以及自由文本中;字段叫 message 也不代表值是安全的。
OWASP 的日志指南列出了访问令牌、认证密码和其他关键秘密等通常不应直接记录的数据。导出前清理是一道补救检查,更长期的改进是在日志产生时就减少不必要的敏感内容。
如果真实凭据已经对外泄露,事后修改副本并不能撤回访问能力,需要按组织的事件处理流程考虑撤销或轮换凭据。
3. 用一个超时日志做对比
下面是待检查的合成记录。SYNTHETIC_TOKEN_NOT_VALID 不是有效 Token,邮箱也是示例地址:
json
{
"event": "checkout.request_failed",
"requestId": "demo_request_17",
"status": 504,
"durationMs": 12500,
"user": {
"email": "demo-user@example.com",
"accountId": "demo_account_42"
},
"request": {
"method": "POST",
"path": "/api/checkout",
"headers": {
"Authorization": "Bearer SYNTHETIC_TOKEN_NOT_VALID"
}
},
"errorCode": "UPSTREAM_TIMEOUT"
}
经过人工检查后,可以为这个排错任务制作如下副本:
json
{
"event": "checkout.request_failed",
"requestId": "request_A",
"status": 504,
"durationMs": 12500,
"user": {
"email": "[EMAIL_REMOVED]",
"accountId": "account_A"
},
"request": {
"method": "POST",
"path": "/api/checkout",
"headers": {
"Authorization": "[CREDENTIAL_REMOVED]"
}
},
"errorCode": "UPSTREAM_TIMEOUT"
}
接手的人仍然知道:POST 请求遇到 504,等待了 12.5 秒,错误码指向上游超时;但没有必要拿到真实凭据和账号信息。
这个副本是手动设计的示例,不是任何工具自动输出的保证。真实日志中的业务内容、路径和错误文本还需要单独检查。
4. 合法 JSON,不等于类型和语义正确
JSON 标准区分字符串、数字、布尔值、null、对象和数组。把数字 504 换成字符串 "[REDACTED]",语法上仍然合法,但依赖数字类型的分析脚本可能失效。
保留必要的数值字段;如果一个数字本身是私密标识符,就根据接收方的 schema 选择删除字段、使用允许的 null,或使用明确说明的合成数字。不要为了保留类型而保留原始隐私值,也不要随手填零、制造出看似真实的业务含义。
关联 ID 也有类似问题:同一请求的多条日志如果都映射成 request_A,可以保留事件关系。但并不是所有脱敏工具都会稳定映射相同值,有的工具按每次匹配分别编号。需要关联分析时,要专门检查这种一致性。
不要把真实 ID 与合成 ID 的对照表附在同一份公开文件里。即使使用了占位符,上下文仍然可能让人识别真实主体。
5. 注意 JSON Lines:它不是一个大 JSON 对象
单个 JSON 文档可以用本地 Python 检查语法:
bash
python -m json.tool sanitized.json
但如果导出文件每一行都是一条独立 JSON,也就是 JSON Lines,不能直接把整份文件当成一个 JSON 对象解析。可以把下面的脚本保存为 validate_jsonl.py:
python
import json
import sys
count = 0
with open(sys.argv[1], encoding="utf-8") as source:
for line_number, line in enumerate(source, start=1):
if not line.strip():
continue
try:
json.loads(line)
except json.JSONDecodeError as error:
raise SystemExit(
f"Invalid JSON on line {line_number}: {error.msg}"
)
count += 1
print(f"Valid JSON records: {count}")
运行方式:
bash
python validate_jsonl.py sanitized.jsonl
这段脚本只检查每条非空记录能否解析,不会清理凭据,也不会验证业务 schema 或判断文件是否适合共享。它遇到第一条错误就停止,不打印整条日志,避免把可能敏感的原始内容再次输出到终端。
6. 最后一次检查,放在导出之后
别只看工具的发现数量。重新打开导出的副本,检查三个问题:
- 文件还可以正常解析吗?字段类型和必要上下文还在吗?
- 是否遗漏了自定义秘密、嵌套内容、内部域名或自由文本?
- 接收方是否确实需要这些信息,发送渠道是否经过组织批准?
优先用本地解析器,不要为「确认 JSON 格式」把真实日志上传到陌生在线校验站。
工具只能辅助检查,不能替你作安全保证
我们开发了 TraceSafe,用于在浏览器本地扫描和清理 HAR、JSON、日志及 cURL 等诊断文本。可以先用内置示例体验,再检查自己的文件和导出结果。
需要明确其边界:模式匹配可能漏掉自定义秘密,也可能误报;文本替换不会自动验证 JSON schema,也不保证同一个 ID 的每次出现都使用相同占位符。上面的类型检查、关联检查和人工复核仍然不可省略。
如果只记住一句话:清理敏感值,保留必要线索,然后验证实际导出的副本,而不是相信「已经脱敏」四个字。
你在排查问题时,遇到过哪些最容易被忽略的敏感日志字段?