直接判断方法:把同一URL的响应头、响应体和扫描判定分开记录,再在时间上做一次对照。如果响应头里的缓存标识在两次扫描之间发生变化,而服务端源站返回的内容没变,那更可能是缓存过期;如果源站返回内容本身变了,且变化能对应到你的修复动作,才更接近真正修复。关键不是看扫描结果从“异常”变成“正常”,而是看这个变化发生在哪一层。
假设你有一个商品详情页,URL安全扫描连续三天报出异常,提示页面中出现了可疑脚本片段。你随后在源站模板里删除了这段脚本,并提交了一次缓存刷新。第二天扫描结果恢复正常。此时不能直接判定修复完成,因为至少有两条路径都能让结果变正常:一是源站真的不再输出可疑脚本,二是CDN或反向代理缓存到期后换成了旧版本或另一个版本。两者在扫描器看来都可能是“正常”,但后续影响完全不同。
这个情境里,真正需要回答的不是“现在正常了吗”,而是“恢复正常的原因是否可重复、可定位、可回退”。如果原因只是缓存过期,那么下一次缓存回源或节点切换时,异常可能再次出现;如果是真正修复,那么无论从哪个节点、哪个时间点请求,源站输出都应保持一致。
区分缓存过期与真正修复,第一步是不要让扫描器替你下结论。你需要拿到同一URL在修复前后的原始响应,重点看三组信息:
Age、Cache-Control、ETag、Last-Modified。如果 Age 从较大值变成接近0,说明这次响应更可能来自回源或新缓存,而不是源站内容本身被修改。一个实际动作是:绕过缓存直接请求源站,例如在请求中带上禁止缓存的头,或临时从源站IP发起请求。如果源站仍然返回可疑片段,那么缓存刷新带来的“正常”只是表象。这个结果会直接改变下一步:你应该继续修源站模板或数据源,而不是停止处理。
缓存过期和真正修复在时间线上通常有不同的特征。缓存过期往往表现为:异常持续一段时间后,在某个固定周期附近突然恢复正常,恢复时间与你的修复动作没有严格先后关系。真正修复则通常表现为:修复动作完成后,第一次回源请求就已经不再包含可疑片段,后续多次请求也保持稳定。
你可以做一个简短的对照记录,假设修复动作发生在某天上午,缓存TTL为若干小时:
如果第2步源站已经干净,第3步缓存过期后也干净,那么更接近真正修复。如果第2步源站仍然脏,第3步却因为缓存过期而显示干净,那么你面对的是缓存过期,不是修复。这个区分会决定你是否需要继续回滚模板、检查数据注入点或调整发布流程。
扫描结果从异常变为正常,只能说明这一次请求的判定结果变了。它不能单独证明源站已经安全。常见合理解释包括:缓存层返回了旧版本、扫描器请求命中了不同节点、扫描规则或阈值发生变化、页面本身是动态渲染而这次返回了不同分支。把其中任何一种当成修复完成,都可能让问题在下次缓存回源或流量切换时重新出现。
更稳妥的做法是保留修复前后的源站响应样本,并明确记录修复动作、缓存刷新动作和扫描结果变化的时间点。如果后续再次出现异常,你可以快速判断它是同一问题复发,还是缓存层再次返回了未修复版本。对于依赖搜索流量的页面,还要注意抓取限制和索引状态是另一层问题:robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,这两件事不能和URL安全扫描的修复判断混在一起。
可以认为更接近真正修复的条件是:源站直连响应中不再出现扫描器报出的可疑片段;缓存过期后多次请求结果一致;不同节点或不同网络位置的返回内容没有差异;并且你的修复动作能解释这个变化。反过来,如果只有扫描器结果变正常,而源站响应、缓存标识或时间线对不上,就应该继续按缓存过期处理。
实际动作上,建议在修复后至少做一次源站直连验证和一次缓存过期后的复验。如果源站直连仍然异常,下一步是回到模板、数据源或发布流程继续修;如果源站直连正常但缓存层仍返回旧内容,下一步是处理缓存刷新和回源策略,而不是继续改源站。这样区分之后,你才不会把一次缓存过期误当成修复完成,也不会在已经修好的情况下反复回滚。