前言:真正让我改定位的,是我自己写的一段脚本

我自己写过一个导出 Chrome 密码和 Cookie 的脚本。

脚本并不复杂,也没有长得像传统意义上的木马。它只是调用系统里已有的能力,读取 Chrome Safe Storage,再去碰 Chrome 用户数据目录里的 Cookie、Login Data 等数据库。

但就是这么一个普通脚本,很多面向普通用户的杀毒软件很难稳定识别。

这件事有点打脸。

因为那时候的 Vestigra,核心定位还是“macOS 安全黑匣子”。我的想法是先不要急着判断谁是病毒,而是把程序从哪里来、被谁启动、做过什么、有没有建立持久化、后来又碰过哪些敏感目录记录下来。等电脑真的出事以后,至少还能还原现场。

听上去没毛病。

但当我真的把密码导出来以后,一个很现实的问题摆在面前:

如果 Vestigra 只能在事后告诉用户“你的密码是这样被拿走的”,那它到底算不算一款安全产品?

这篇开发日记,就从这次定位被推翻开始。

一、一开始,我只想解决“电脑出事后什么都说不清”

很多安全事件,用户最后只能看到结果:

  • 加密货币资产没了;
  • Token 被窃取了;
  • Cookie 被导出了;
  • 开发者机器遭遇了供应链攻击;
  • 本地环境已经被污染,但不知道从哪里开始的。

真正关键的问题反而没人答得出来:

  • 它是什么时候进来的?
  • 是谁下载的?
  • 第一次运行发生在什么时候?
  • 它怎么建立持久化?
  • 它什么时候开始读取敏感数据?
  • 密码最后到底是怎么没的?

对普通用户来说,整个过程就是一个黑盒。

所以我最早给 Vestigra 定的目标很克制:先把 macOS 上的关键行为记录下来,再把零散事件串成一条人能看懂、能追溯、也能复核的 Story。

例如系统底层看到的,可能只是“某个进程写了一个 plist”。但人真正需要看的应该是:

1
2
3
4
5
6
Codex
→ zsh
→ 某个脚本
→ 写入 LaunchAgent plist
→ 注册启动项
→ 后续访问敏感目录或发起网络连接

真实安全问题很少由一个孤立事件构成,它通常是一条链。

我当时以为,只要把这条链讲清楚,产品价值就成立了。

后来才发现,我还是想简单了。

二、底层 Event 越多,离用户能看懂的真相可能越远

macOS Endpoint Security 给出的事件非常细碎。如果只是把事件一股脑存下来,最终很容易得到几万条“技术上都是真的、但人根本看不懂”的日志。

所以 Vestigra 第一阶段最重要的不是多收日志,而是 Story:

  • 某个程序从哪里来;
  • 谁启动了它;
  • 它什么时候第一次运行;
  • 它写了哪些持久化配置;
  • 它后来访问了什么敏感目录;
  • 哪些节点有直接证据;
  • 哪些环节没有观察到。

这时候我又踩进了另一个坑。

Story 太好读了,好读到它很容易冒充事实。

于是我不得不给整个系统立下一条后来越来越重要的规矩:

1
2
3
4
Ledger 是事实源。
Story 是解释。
Projection 是缓存。
Gap 也是证据的一部分。

例如“某个程序写了 LaunchAgent”可以是 observed evidence;但“它一定在进行恶意持久化”已经是解释。

解释当然有价值,否则用户还是看不懂。可解释必须带着证据、上下文和不确定性,不能穿上一件“事实”的外套。

所以 Vestigra 后来必须明确区分:

  • 真实观察到的事件;
  • 基于事件生成的解释;
  • 从外部导入的信息;
  • 当前没有覆盖到的区域;
  • 保护能力已经降级的状态。

有三句话,我现在几乎把它们当成产品底线:

1
2
3
Not observed 不等于 did not happen。
Rule hit 不等于 malicious。
AIProposal 不是 observed evidence。

我原本想消灭安全黑盒。如果最后又用一段看起来很聪明的 Story,把推断包装成事实,那只是亲手造了另一个黑盒。

三、只有 Story 以后,用户还是会追问:那你挡住了吗?

做了一段时间以后,我开始看 macOS 上面向普通消费者的安全产品,也开始重新想 Vestigra 到底给谁用。

对开发者、研究者和高阶用户来说,记录、追溯和 Story 已经很有价值。但普通用户的第一反应通常不是“你能不能帮我做事件调查”,而是更直接的一句:

你有没有保护我?

这句话直接把最初的定位推翻了一半。

Vestigra 不能永远只做:

1
记录 → 追溯 → Story

它还得往前走一步:

1
记录 → 追溯 → Story → Protection

但我也不想把它做成一套“发现可疑东西就自动 kill、delete、block,然后宣布世界已经安全”的系统。

安全产品一旦开始默认执行高风险动作,它不只可能保护用户,也可能破坏用户。

所以我给 Protection 加了一条边界:默认应该是 Record、Explain、Warn、Suggest Investigation,以及 Product Data Self-Protect。真正高风险的响应,需要明确的策略判断、预览、确认、审计和回滚语义。

这条路看起来慢,也不够“杀伐果断”。

但安全软件最不该做的,就是拿用户的机器替自己的自信买单。

四、Chrome 脚本让我从“识别坏样本”转向“保护敏感行为”

Chrome 密码导出脚本真正改变我的地方,是它让我意识到:

需要保护的不只是某个已知恶意样本,而是一类敏感行为。

一个程序可能没有病毒特征,也不在任何已知样本库里,但当它开始读取 Chrome Safe Storage、访问 Chrome 用户数据目录、打开 Cookie 或 Login Data 时,这条行为链已经值得警惕。

理论上,能够访问这些目录的主体应该很有限:

  • Chrome 主程序;
  • Chrome Helper;
  • 必要的 updater 或受信组件。

其它程序来碰这些数据,至少应该被记录、解释和告警;在当前能力确实覆盖、规则也明确的情况下,才考虑受控拦截。

这件事把 Vestigra 推向了两个概念:Sensitive Authority 和 Behavior Protection。

Sensitive Authority 不是“为了安全把用户内容全读一遍”,而是围绕高价值资产采集 metadata,回答几个问题:

  • 谁拥有权限?
  • 谁触碰了 secrets?
  • baseline 有没有发生变化?
  • 触碰之后又发生了什么?
  • 哪些地方仍然不确定?

这些资产可能包括 TCC / FDA 授权、Keychain 或 secret stores、浏览器 secrets / cookies、开发者凭据和云服务 credentials。

这里我必须反复强调一个边界:

metadata, not content。

保护 Chrome 数据,不等于默认读取用户的 Chrome 内容。Vestigra 也不应该默认采集文档正文、聊天记录、邮件正文、网络 payload 或 TLS 明文。

五、我很快又发现,“保护 Chrome”这句话说大了

产品定位刚想清楚,工程现实马上又泼了一盆冷水。

macOS Endpoint Security 并没有提供一个“以后每次 read/write 都交给你决定”的魔法开关。以 AUTH_OPEN 为例,它控制的是 open 阶段的 flags,并不代表应用可以持续仲裁文件打开后的每一次 I/O。

所以“Vestigra 可以保护 Chrome 数据”这句话虽然好懂,但不够准确。

我最后只能把承诺改得很长:

对当前已支持、已验证、已编译进入 ES AUTH 面的 Chrome 数据访问操作,进行 metadata-only、签名主体 allowlist、domain-separated、可审计的行为保护。

很绕,不像一句好卖的宣传语。

但这才是当前真实的工程边界。

每一个进入 enforce rule 的高层 operation,都必须能答出这些问题:

  • 对应哪个 AUTH event?
  • request parser 怎么解析?
  • evaluator 根据什么判断?
  • response 怎么执行?
  • audit 怎么落下?
  • runtime degraded 时,用户能不能看见?

有一环没打通,就不能靠一个漂亮的功能名假装已经保护了。

六、最后,整个系统只能走向 Rule First

保护能力加进来以后,另一个问题也爆了出来:如果所有逻辑都写死在代码里,系统很快就会失控。

哪些事件需要采集?哪些行为要生成 Story?哪些目录属于高价值资产?什么情况只记录,什么情况告警,什么情况才允许进入 Response?

这些判断不能散落在一堆 if 里。

于是 Vestigra 开始走向 Rule First:

1
2
3
4
5
采集策略 → rule / config
解释策略 → story pattern
保护策略 → policy / rule
响应策略 → ResponseGate
验证策略 → replay / gate

规则也不再只是一个阈值配置,而是产品承诺的表达方式。

例如 LaunchAgent 相关行为,不应该停在“看到写 plist 就报警”。更完整的链路应该是:规则命中关键行为,生成 RuleEvaluationRecord,保留 match bindings,把它作为 investigation seed,向上追溯来源、向下观察后续行为,再生成 Story;必要时给出 warning 或 investigation suggestion,最后还能导出 case,并在其它环境里 verify / replay。

到这里,Vestigra 已经不再只是日志收集器,也不只是一个拦截器。它开始变成一个证据驱动的本地安全 runtime。

目前的结论:我仍然不想造另一个黑盒

回头看,Vestigra 的第一段演化大概是:

1
Event → Story → Evidence → Rule → Protection → 受控响应

每走一步,前一个阶段都会暴露新的问题:

  • 只有 Event,用户看不懂;
  • 只有 Story,用户会问有没有保护;
  • 有了 Protection,就必须说清能力边界;
  • 有了 Rule,就必须能审查、导出、回放和验证。

所以我目前给 Vestigra 的定位是:本地优先、证据中心、规则驱动、AI 辅助、受控响应的 macOS EDR-like runtime。

这个定位以后可能还会改。毕竟前面已经被自己推翻过一次了。

但最底层的产品信念暂时没有变:安全产品不应该制造另一个黑盒。它应该老老实实告诉用户,我看到了什么、为什么这么判断、能做什么、不能做什么,以及哪些地方根本没有看到。