你录制的测试,可能正在把 session cookie 提交进代码库
写 API 测试最快的办法,就是录一个真实请求再回放。而泄露凭据最快的办法,也正是这一步。刚抓下来的请求里带着还活着的 session cookie、一个 Authorization: Bearer 头,JSON body 里说不定还有身份证号或卡号。原样存成 spec,这些全进了 git,明文躺在别人会 clone 下来的文件里。
之所以会这样,是因为按下保存的那一刻,省事的做法和安全的做法看起来一模一样。请求跑得通,测试能过,凭据就躺在下面三行、没人会去看的地方——直到哪天它出现在一次凭据泄露扫描的结果里。
Hover 在写文件前剥掉了什么
Hover 把录好的请求 crystallize 成一份待提交的 .api-test.spec.ts 时,会先让它过一遍消毒器,一共三轮:
带凭据的 header 直接删掉:cookie、set-cookie、authorization、proxy-authorization、x-api-key、x-auth-token、x-amz-security-token。这些不是打码,而是直接移除——CI 里的认证来自 Playwright 的 storageState fixture,不靠硬写进文件的字符串。
命中凭据名的 query-string 值会被打码:URL 里的 ?token=...、?api_key=... 是常见的泄露点,值会被抠出来,换成占位符。
JSON body 字段按 key 名打码:password、token、secret、api_key、access_token、auth、ssn、credit_card,还有它们的各种拼写变体。匹配器覆盖所有 JSON 值类型,不只是字符串。以数字形式发送的身份证号("ssn": 123456789)过去会从只认字符串的匹配器底下溜过去,直接进到提交的文件里。现在不会了。
只留一份 alternation,覆盖范围就不会走偏
早先的版本维护着两份独立清单,一份管 URL 参数,一份管 body 字段。结果两份走偏了:auth 和 apikey 在 URL 清单里,body 清单里却没有,于是名为 auth 的 body 字段漏了出去,同一个名字在 query string 里反倒被拦下。两份"本该一致"的清单,迟早会不一致。
现在两个匹配器都出自同一份 alternation。要加一个凭据名,加一次就够,URL 那轮和 body 那轮都会认。你不可能修了一个漏掉另一个,因为要修的只有一处。
它删了什么,你看得到
消毒器会把剥掉或打码的 header 名和字段名列出来,Hover 再展示给你。保存 spec 不是一次悄无声息的改写。你会看到"dropped: cookie, authorization; masked: ssn",于是清楚这个回归测试是真的,秘密也不在里面。认证在运行时从 fixture 取回,断言照跑,文件可以放心提交。
这是 先探索、再 crystallize 这套思路里不那么体面的另一半。让 AI 写测试,只有当它留下的产物是你愿意提交的东西,才谈得上有用。一份带着活 token 的 spec 算不上这样的产物,所以消毒器在出口处运行,每次都跑。
在你自己的应用上试试 Hover。
把 Hover 的 MCP 加到你已经在用的编码 agent。它探索你的应用,结晶出你自己拥有的纯 Playwright spec。
npm i -g @hover-dev/mcp && claude mcp add hover -- hover-mcp阅读快速开始 →