分享排障日志前的一道防线:离线脱敏工具的区间替换与失效设计
作者:lgbisha。本文基于本人已公开的「隐迹 · 离线日志脱敏」1.0.0,使用 AI 辅助撰写与校对;实现细节和示例均对照实际源码与运行结果核实。示例中的认证值明确虚构,不包含真实账号、日志或云凭据。
昨天完成这个静态网页工具后,我重新检查了一个容易被忽略的问题:日志里的敏感内容不只存在于 password 字段,Cookie 整行、认证头和 URL 参数也可能带着认证信息。工具如果只是把几个词替换成星号,很容易产生“看起来处理过了”的错觉。
这篇文章不重复部署流程,而是记录这次实现中三个具体取舍:按原文区间替换、只允许导出当前版本的结果,以及明确说明自动规则的能力边界。
一、先缩小工具的权限,而不是先扩大正则列表
这个版本是普通 HTML、CSS 和 JavaScript 页面。运行时不需要安装包、不调用模型,也不要求 API Key。处理对象只有用户主动粘贴的文本,或主动选择的一个 UTF-8 文件;不会读取浏览器 Cookie、环境变量或其他文件。
代码没有远程脚本、统计请求或字体依赖,也不把原文写入 localStorage、IndexedDB、地址栏和控制台。需要强调的是,这是本项目的代码行为,不是对浏览器扩展、操作系统剪贴板或截图软件的安全承诺。
输入上限按 UTF-8 字节数计算,为 1 MiB。这个约束既限制处理量,也避免把字符数误当字节数。空文本、超限内容以及含空字节的输入有各自的错误提示;不把“没有输出”当成成功。
二、避免逐轮修改字符串:先找区间,再一次构建输出
引擎会先在原始文本上收集候选区间,每个候选包含起点、终点、类别和优先级。它使用支持匹配索引的正则表达式,将捕获组映射回原文位置。
随后按起点、同起点的规则优先级和范围长度排序,对重叠区间做消解,最后沿原文从前向后一次构建结果。这样,前面的替换不会改变后续规则正在引用的位置,也不会让后面的规则去处理刚生成的占位符。
这里的优先级主要处理同起点的候选选择,重叠区间会合并覆盖范围;不能把它理解为适用于任意语法结构的通用解析器。例如一个 Cookie 头里又出现名为 token 的字段,输出应当保守覆盖整行认证值,而不是留下部分 Cookie。
占位符按类别编号,例如 [AUTH_001] 和 [TOKEN_001]。同次处理内,同类别、相同原值复用同一标记。这个映射仅服务于当前计算,不跨会话建立凭据身份库。
三、用一段完全虚构的日志验证行为
2026 年 10 月 23 日,我直接调用项目的 redactText 函数,输入如下文本。所有带 FAKE 的值都不可用于认证;域名使用 example.invalid。
Authorization: Bearer FAKE-DEMO-NOT-VALID
Cookie: demo_session=FAKE-COOKIE-NOT-VALID
GET https://example.invalid/callback?ticket=FAKE-TICKET-NOT-VALID&trace_id=demo-42
{"password":"FAKE-PASSWORD-NOT-VALID","requestId":"demo-42"}
{"token":"FAKE-SAME-TOKEN-NOT-VALID"}
{"token":"FAKE-SAME-TOKEN-NOT-VALID"}
实际输出是:
Authorization: [AUTH_001]
Cookie: [COOKIE_001]
GET https://example.invalid/callback?ticket=[TOKEN_001]&trace_id=demo-42
{"password":"[SECRET_001]","requestId":"demo-42"}
{"token":"[TOKEN_002]"}
{"token":"[TOKEN_002]"}
这次结果为 6 个替换位置:认证信息 1、Cookie 1、密码与密钥 1、令牌与票据 3。TOKEN 类别有 3 次命中,但只有两个不同标记,因为最后两行的原始 token 相同。trace_id 和 requestId 保留,便于继续关联排障上下文;这不代表所有上下文标识都天然适合公开。
四、比“能替换”更重要的状态约束:旧结果立即失效
用户先处理文本 A,得到结果 A,然后又输入文本 B。如果复制按钮仍然可用,就可能误把结果 A 当成 B 的处理结果。只验证正则是否命中,无法发现这类界面错误。
本工具在原文或选项变化时增加页面版本号,清除旧结果并使导出状态失效,必须重新处理才能复制和下载。异步文件读取也记录启动时的版本:如果读取期间用户更改输入或清空页面,旧回调不能再覆盖新状态。
复制只有在剪贴板调用真正成功后才提示成功。如果浏览器拒绝访问,页面选择结果并提示手动复制,不会自动退回复制原文。下载名固定为 redacted-log.txt,不把源文件名顺带带出去。
五、测试数量必须和验证范围一起说明
2026 年 10 月 23 日,在未修改产品代码的前提下,我重新执行了:
npm run check
npm test
语法检查通过,Node 内置测试结果为 61 项通过、0 项失败。这些结果验证既定样例、输入边界、规则和重叠处理等行为,不是“能识别全部秘密”的证明,也不能替代浏览器交互验证或独立安全审计。
这一点会直接影响文案:不写“彻底清除所有敏感信息”,而是写“处理常见格式,并在分享前人工复核”。没有命中不等于安全,有命中也不等于可以直接公开。
六、必须保留的限制
- 规则不能可靠覆盖所有裸密钥、未知字段、编码内容、折行和畸形结构,也不处理图片及附件中的信息。
- 输出按纯文本生成,不保证任意 JSON、脚本或配置仍然能解析、执行,也不保证诊断语义完全不变。
- 清空只移除页面内容、映射和导出状态,不是取证级内存擦除,不能撤回已复制、已下载或已发送的内容。
- 手机号和邮箱规则可关闭,认证与凭据规则始终启用;无论如何配置,都需要按分享对象复核输出。
- 已经暴露的真实凭据不能靠修改已发日志来补救,应到所属平台停用或更换。
结语
这次实现最值得保留的不是正则表达式数量,而是约束:只处理主动输入、保持替换位置一致、拒绝导出过期结果,以及把不保证的事情说清楚。日志脱敏应当是分享前的一道防线,而不是允许随意公开日志的通行证。
完整代码及使用限制可在 GitCode 公开项目中查看:LGBISHA/offline-log-redactor,作品名为「隐迹 · 离线日志脱敏」。本文不包含真实凭据,也不以测试通过代替安全承诺。
- 点赞
- 收藏
- 关注作者
评论(0)