26 KiB
Browser Profile 自动推断与 AI 协作架构
1. 产品决定
自动推断 Profile 不是明文网关的辅助功能,而是浏览器现场的默认完成路径。
用户不应先理解混淆变量、复制密钥、编写包装函数,再手工配置参数路径和输出映射。正常流程必须从一次真实业务操作开始:
用户执行登录 / 查询 / 提交
-> Recorder 生成有界业务 Trace
-> 确定性推断器关联明文点、页面调用和请求字段
-> 已知模式直接生成候选
-> 未知模式请求 AI 解释业务帧和参数语义
-> 必要时引导用户再执行一次操作以捕获业务闭包
-> 编译为文档绑定的 Profile
-> 使用录制样本做页面内回放校验
手写 JavaScript 保留为高级模式,不再作为主流程或文档中的首选方案。
本设计不包含“发送真实 HTTP 请求验证”。真实请求仍由 Yak / Web Fuzzer 的既有数据面负责。本阶段只负责发现、推断、捕获、编译和页面内样本校验。
2. 用户结果
以一次 CryptoJS 调用为例,默认界面应展示:
已识别请求转换
POST /api/login
JSON 明文 -> CryptoJS.AES.encrypt -> body.encryptedData
输入 argument 0 <- 请求明文 JSON
Key argument 1 <- 页面内 WordArray · 16 B
IV options.iv <- 页面内 WordArray · 16 B
模式 CBC / Pkcs7
输出 toString -> URL encode -> encryptedData
证据 4 项 · 高置信度
[生成 Profile]
_0x67b862 一类混淆名称只能出现在折叠的原始证据中。主界面使用 Key、IV、明文输入、请求字段 等语义角色。
用户应能回答三个问题:
- 插件为什么认为这是加密链路;
- 哪些结论是确定事实,哪些是推测;
- 还需要用户执行什么操作才能完成 Profile。
3. 设计原则
3.1 证据先于 AI
指纹相等、请求字段解析、调用顺序、运行时对象类型和调用栈属于确定性证据。AI 不重复判断这些事实,只消费其结构化结果。
3.2 AI 不能成为执行边界
AI 可以:
- 给业务 frame 排序;
- 将参数标注为 payload、key、iv、nonce、timestamp 或 signature;
- 从有限源码片段中解释序列化和包装步骤;
- 在多个候选之间给出理由;
- 建议下一次捕获点。
AI 不可以:
- 直接提交任意 JavaScript 作为生产 Profile;
- 引用不存在的事件、frame、参数或页面函数;
- 读取或输出 key、Cookie、token、密码等原始值;
- 绕过 grant、document、origin 或人工接管状态;
- 将猜测标记为已经验证的事实。
3.3 页面是执行环境,不是密钥导出器
Key、IV、CryptoKey、key promise、WASM 实例和闭包变量继续保留在原页面。Profile 只保存页面内 opaque callable 引用和经过校验的参数映射。
3.4 已知模式不依赖 AI,未知模式不依赖库清单
WebCrypto、CryptoJS、JSEncrypt 以及后续 sm-crypto、node-forge 等已知模式,连同 URLSearchParams、JSON、FormData 和常见编码链,应优先由确定性规则推断。AI 只处理业务语义和未知代码,避免增加延迟、成本和不确定性。
录制协议只暴露统一的 crypto 事件,库差异进入结构化 adapterId / providerKind / family / operation / algorithm / mode / padding / encoding / state / key metadata。推断器、时间线、Deep Capture 和 Agent 不再分别判断 webcrypto、cryptojs 等事件类型。新增密码库时只扩展 MAIN-world adapter、扩展自带的 manifest 和受限元数据归一化器,不扩展整条产品协议。
已知 adapter 只负责提供更准确的参数角色、算法和状态语义,不是通用性的唯一来源。对于 ESM/Webpack 闭包、Worker、WASM 或完全未知的业务封装,系统必须从请求/消息边界和调用栈恢复上层业务 callable;算法尚未命名不能单独成为 insufficient-evidence。adapter 协议的开放化、Worker/MessagePort 边界、高价值库优先级与反靶场特化验收见 FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md。
3.5 无兼容负担
插件尚未正式投入使用。页面配方、运行时适配器和 Transform Profile 可以直接收敛到新模型,不保留旧数据迁移或双写逻辑。
4. 总体架构
MAIN-world Recorder
| bounded events + opaque handles + semantic argument metadata
v
Evidence Normalizer
| request fields / call slots / encodings / exact & normalized links
v
Evidence Graph
| proven edges + supported edges + hypotheses
+-----------------------+
| |
v v
Deterministic Inference AI Analysis
| known patterns | frame ranking / semantic labels / unknown code
+-----------+-------------+
v
Candidate Merger
| schema validation + evidence reference validation
v
Pipeline Compiler v2
| page callable graph, no arbitrary generated code
v
Local Sample Replay
| deterministic compare or structural assertions
v
Document-bound Profile
推断计算在扩展后台完成。Yakit、Options 和 AI Agent 读取同一候选结构,不各自实现一套启发式规则。
5. Evidence Graph
5.1 节点
type EvidenceNode =
| RecordingEventNode
| RecordedValueNode
| RequestFieldNode
| CallableNode
| CallArgumentNode
| StackFrameNode
| SourceExcerptNode
节点只使用录制会话内稳定 ID。原始敏感值不是图节点属性。
5.2 边
type EvidenceStrength = "proven" | "supported" | "hypothesis"
type EvidenceEdgeKind =
| "exact-value"
| "normalized-value"
| "parent-call"
| "same-trace"
| "stack-frame"
| "argument-role"
| "request-destination"
exact-value:同一录制盐下的指纹完全相同;normalized-value:经过有界白名单转换后相同,例如 URL decode、JSON field extraction 或 Base64 表示;parent-call:Recorder 的同步父调用关系;same-trace:弱证据,只证明时间和用户操作相关;hypothesis:只能由 AI 或启发式产生,必须列出依据。
5.3 请求边界归一化
网络事件在边界处解析,不全局 Hook JSON.stringify 或 encodeURIComponent:
- JSON:递归提取最多 64 层、100,000 节点;
application/x-www-form-urlencoded:字段级 URL decode;FormData:字段名、字符串值和文件元数据;- Headers:规范化名称但保留原始大小写用于展示;
- Query:字段级解析;
- 原始 body:保留整体指纹和类型。
归一化候选只允许白名单操作并设置总预算。不得对每个值进行无界编码组合爆炸。
5.4 参数语义
Recorder 对已知库记录参数角色而不是变量名:
interface CallArgumentEvidence {
index: number
role: "data" | "key" | "iv" | "algorithm" | "options" | "signature" |
"salt" | "nonce" | "aad" | "unknown"
dataType: string
byteLength?: number
replaceable: boolean
retained: boolean
summary?: string
}
例如 CryptoJS AES:
argument 0:data,可替换;argument 1:key,不导出,页面内保留;argument 2:options,提取 mode、padding 和 IV 长度,不提取 IV 值。
例如 JSEncrypt RSA:
argument 0:UTF-8 data,可替换;对象输入按稳定 JSON 序列化后再交给原函数;- receiver:保留实际 JSEncrypt 实例,不重建、不导出;
- key:只记录 public/private、模数位数和本次录制随机加盐的指纹;
- padding:记录
PKCS1-v1_5等可解释元数据; - output:记录 Base64 形态并与 JSON/Form/Header/Query 请求字段做 exact link;
- 公私钥 PEM、模数、指数和页面实例永不进入候选或 AI 上下文。
如果一次 RSA 输出精确进入一个请求字段,且原函数、receiver 和参数模板仍在当前 document 中,候选可以直接进入 ready,不要求用户填写函数表达式或先进入 Deep Capture。
6. 统一 Page Callable
当前页面配方和深度捕获适配器表达的是同一概念:在当前文档中可重复调用的页面函数。两套注册表应合并为 BrowserPageCallable。
interface BrowserPageCallable {
id: string
kind: "recorded-call" | "business-closure" | "global-function"
name: string
target: BrowserTarget
lifecycle: "document"
inputSlots: CallableInputSlot[]
output: CallableOutputShape
provenance: {
recordingId?: string
traceId?: string
eventId?: string
frameId?: string
sourceUrl?: string
lineNumber?: number
}
}
recorded-call 保存原函数、receiver、固定参数模板和可替换槽位;business-closure 保存 CDP 暂停时捕获的业务函数与闭包;两者使用同一执行、授权、生命周期和审计接口。
Profile 不再引用 recipeId 或 adapterId,只引用 callableId。
7. Pipeline v2
手工 JavaScript 中常见的 JSON 序列化、编码、调用和封装应变成可审计的类型化节点:
type PipelineNode =
| { kind: "context.read"; path: string }
| { kind: "builtin"; operation: BuiltinOperation; inputs: NodeRef[]; options?: object }
| { kind: "page.call"; callableId: string; arguments: NodeRef[] }
| { kind: "output.write"; destination: string; source: NodeRef; encoding: ValueEncoding }
首批 BuiltinOperation:
value.literal
json.stringify
json.parse
text.toString
url.encode
url.decode
base64.encode
base64.decode
hex.encode
hex.decode
object.pick
object.compose
form.compose
value.literal 只允许字符串、数字、布尔值或 null,用于编译器生成固定的协议元数据,例如表单
Content-Type。它不接受输入,也不能持有函数、对象或页面秘密。
每个节点有明确输入输出类型和大小预算。未知操作不能通过 AI 临时创造;用户确实需要自定义代码时,进入独立的高级节点,并沿用程序 Eval 的高风险授权。
8. 推断候选
候选不是立即生效的 Profile:
interface BrowserProfileInferenceCandidate {
id: string
recordingId: string
traceId: string
target: BrowserTarget
request: { eventId: string; method: string; url: string }
direction: "request" | "response"
status: "ready" | "capture-required" | "mapping-required" | "insufficient-evidence"
confidence: { score: number; level: "high" | "medium" | "low" }
summary: string
pipeline: PipelineNodeDraft[]
evidence: InferenceEvidenceRef[]
missing: InferenceMissingStep[]
aiContext: BrowserInferenceAIContext
}
置信度不是 AI 的主观百分比。分数由固定规则产生,并在 UI 中解释:
- 请求字段与加密输出 exact link:强加分;
- 可重复 callable 已保留:强加分;
- 同一用户 Trace 且顺序正确:中等加分;
- 仅时间接近:弱加分;
- 多个同分候选:降分;
- 缺少输入映射或输出封装:状态不能为 ready。
9. 自动业务函数捕获
低层 CryptoJS.AES.encrypt 或 crypto.subtle.encrypt 往往不足以构造完整线上报文。推断器应把它作为断点入口,然后寻找上层业务函数。
候选指出需要业务 callable
-> 用户点击“自动捕获完整加密流程”
-> 插件在已知低层调用处 arm 一次性断点
-> 用户重复相同操作
-> 页面暂停并立即显示控制面
-> 后台排除 Hook/依赖帧,并使用多来源共同祖先提示排序页面帧
-> 纯函数用 selected-frame;负责 DOM 取值/组包/发送的函数用 request-transaction
-> 页面立即恢复
-> 新明文映射到参数或页面控件,仅返回被拦截的线上 envelope
录制器只从每个来源事件的有界同步栈提取页面帧提示,并对 functionName + script URL 求交集;支持来源更多、平均深度更浅的共同祖先优先。捕获入口选择最早已确认的密码来源,而不是已经离开上层异步函数后的 Fetch 边界。后台再结合真实 CDP scriptId、函数位置、来源分类和副作用检查做最终选择,因此前端不能通过提交 URL、行号或函数名把任意对象伪装成推荐帧。
当最高候选唯一、可解析且未发现副作用时,默认路径使用 selected-frame。如果多个密码来源的最近共同页面祖先本身包含网络、DOM 或条件导航,系统不会跳过它去选更外层的事件 handler,而是建立 request-transaction:保留真实函数、receiver 和固定参数,在页面内替换明文控件,拦截唯一的目标 Fetch/XHR/Beacon/Form,校验所有预期输出字段后回滚 DOM。
存储副作用、多个或未授权请求、无法唯一绑定函数、或共同祖先证据并列时,系统保持页面暂停并解释原因。函数引用表达式只存在于高级模式。页面暂停不等待远程 AI;AI 只能在页面恢复后基于同一份有界证据做解释和候选补丁。
函数捕获后,后台从 Function.prototype.toString 恢复包括默认参数在内的有序参数名。单参数业务函数默认读取整个逻辑 Body;多参数且名称可靠时,引导配置生成 body.<parameter> 读取节点;arg0 这类占位名不会被冒充为已确认字段。Options 同时从已授权暂停帧的 local/block/closure scope 取同名原始值,构造一次性的本地回放 Body。完整暂停作用域始终只存在于当前会话;只有用户明确生成并保存明文网关后,选中的短时样本才会复制到独立的本机回放草稿。该草稿按 profileId + request/response 隔离,不写入 Profile、Bridge、审计、Yak/AI、诊断或导出,并可由用户单独清空。
9.1 多密码调用按请求建图
一个请求可能同时包含 AES ciphertext、RSA-encrypted session key、HMAC signature、nonce 和 timestamp。即使每个低层输出都与请求字段精确匹配,也不能把这些调用分别保存后独立回放:它们可能共享同一随机 key、IV、nonce 或闭包状态。
推断器因此按请求边界合并多个来源,生成一个 request-level candidate:
plaintext -----------------> AES.encrypt ----------> body.data
dynamic AES key -----------> JSEncrypt.encrypt ----> body.encryptedKey
canonical request fields --> HMAC.sign ------------> header.X-Sign
|
+-- 同一上层业务 callable 保证动态值一致
界面展示每个密码调用及其线上目标,但状态固定为 capture-required。用户点击“自动捕获完整加密流程”时,Deep Capture 优先在仍保留上层业务调用栈的密码来源处武装断点,并捕获一次上层业务封装;系统不会把多个看似 ready 的低层调用拆成多个可执行 Profile,也不会误导用户反复缩短已经足够短的录制操作。
9.2 请求事务的输入与输出契约
request-transaction 对明文只暴露一个 body 输入槽,对 Pipeline 返回被页面业务代码生成的整个请求 Body。因此 AES + RSA 之类多输出流程会直接编译为:
context.read(body)
-> page.call(sendDataAesRsa 请求事务)
-> output.write(body)
事务保留暂停现场的 URL/event/receiver 等固定参数。逻辑 Body 是对象时,先按 input name/id 向页面控件做同名映射;参数名明确是 payload/data/body/request/params/input 时才直接替换参数。已混淆的单参数如果其保留值解析后等于目标 URL,必须继续保留,不得被明文对象覆盖。
10. AI Agent 集成
10.1 绑定资源
Yakit 从浏览器集成页启动 AI 分析时,附加一个类型化资源:
AttachedResourceInfo.type = browser_session
AttachedResourceInfo.key = context
Value 只在 Yak 进程内解析,包含 device、grant、document、selected trace 和 candidate ID。渲染给模型的内容只包含安全摘要,不暴露 device token、grant secret 或录制值。
资源必须绑定:
timeline session
AI task
deviceId
grantId
tabId + frameId + documentId + origin
expiresAt
10.2 Agent 工具
不要把几十个 Bridge RPC 原样暴露给模型,也不要提供通用 method + params 工具。首批提供三个领域工具:
browser_observe
page summary / actionable nodes / trace / inference / status / diff
browser_inference
list candidates / inspect evidence / arm capture / choose callable /
propose mapping / compile candidate / local replay
browser_act
stable node action / tab activation / human handoff
工具回调从当前 AI task 的 browser_session 资源解析绑定,AI 参数中不存在 deviceId、grantId 或任意 Bridge method。
browser_observe 默认只读;browser_inference 的读取和推断无需额外确认,arm debugger、创建 callable 和发布 Profile 使用现有细分 scope;browser_act 遵循 Agent review policy 和人机接管状态。
10.3 AI 输出 Schema
AI 只能返回候选补丁:
interface AIInferencePatch {
candidateId: string
labels: Array<{ evidenceId: string; role: SemanticRole; reason: string }>
preferredFrameId?: string
argumentBindings?: Array<{ slotId: string; contextPath: string; reason: string }>
suggestedBuiltins?: Array<{ operation: BuiltinOperation; evidenceIds: string[] }>
unresolved: string[]
}
Candidate Merger 必须验证所有 ID 存在、document 未变化、操作在白名单内、映射路径合法。验证失败只产生新的待处理项,不能退化为执行 AI 代码。
11. UI / UX
录制是入口,自动推断是录制完成后的主结果。三列工作台保持不变:
Trace 列 | 数据流与候选 | 推断证据 / 下一步
右侧主区域按状态显示:
ready:一键生成 Profile;capture-required:解释原因并提供“自动捕获完整加密流程”;mapping-required:只让用户选择少量无法确定的明文字段;insufficient-evidence:建议重新录制,并明确缺少哪类证据。
证据采用三种强度:
- 已证实:实线和明确措辞;
- 有支持:普通文本并展示依据;
- 待确认:虚线或次级文本,不使用成功色。
AI 是候选的解释者,不单独占据一个聊天面板。主要入口是“让 AI 深入分析”,结果回填到同一证据区域。需要继续对话时再打开 Yakit AI 会话,并携带相同 browser_session 资源。
手工 Pipeline 编辑器移入“高级编辑”,默认只展示推断出的可读流程和少量可修改字段。
默认 Profile 编辑器不是节点画布,而是三个业务决定:
1. 明文从哪里来
2. 交给哪个页面函数
3. 线上结果写到哪里
当第三步选择“写入表单字段”并填写 encryptedData 时,编译器自动生成
form.compose(keys=["encryptedData"])、固定 Content-Type、Header 输出和 Body 输出。用户不需要看到或填写
keys、节点 ID、输入引用和输出引用。已有非规范 DAG 不会被静默改写,只能继续在高级模式中编辑,或由用户明确替换为引导流程。
12. 性能预算
- 单次快照最多 500 事件、每事件 48 个 evidence;
- 图构建使用 fingerprint/path 索引,目标复杂度
O(E + V); - normalized link 每值最多生成 8 个白名单变体;
- 候选最多 16 个,发送给 AI 的候选最多 3 个;
- scope 每次最多 8 个 frame,源码片段按需读取并限制总字节;
- 推断结果按
recordingId + event revision缓存,增量追加事件时只处理新增部分; - 不在页面主线程执行全量源码搜索、AST 构建或全局 JSON/URL 编码 Hook;
- Pipeline 在目标 document 内一次执行完成,每次请求/响应只跨扩展到页面边界一次,不按节点往返;
- 页面暂停路径绝不等待网络或 AI。
13. 隐私与授权
- 默认推断只使用指纹、类型、长度、路径、算法摘要和源码位置;
- 敏感录制预览即使被用户开启,也不自动进入 AI context;
- Key、IV、CryptoKey 和闭包值只显示语义、类型与长度;
- 源码片段可能包含硬编码 secret,发送 AI 前先进行字面量脱敏并由用户授权;
- 推断读取使用
browser.recording.read; - scope/source 深入读取使用
browser.debugger.read; - arm/resume 与 callable 创建使用
browser.debugger.control; - callable 创建、执行与本地回放使用
browser.callable.execute;从暂停 frame 捕获 callable 还需要browser.debugger.control; - Profile 发布使用
browser.transform.manage; - document、origin 或 grant 变化后候选立即标记 stale,不静默重绑。
14. 生命周期与恢复
Profile 是 document-bound。刷新后不能继续调用旧闭包,但推断定义可以保留为恢复计划:
页面刷新
-> callable stale
-> Profile disabled
-> 插件按原 operation / script / route 重新 arm
-> 用户正常执行一次业务操作
-> 重新捕获 callable
-> 本地样本校验
-> 用户确认后重新启用
恢复计划不保存 key 或源码计算结果,只保存捕获入口、业务 frame 特征、参数语义和映射结构。
15. 分阶段实现
P0:证据与候选基线
- [已完成] 使用统一
crypto事件记录 WebCrypto / CryptoJS / JSEncrypt / sm-crypto / node-forge 的 adapter、provider kind、family、调用、参数角色、类型、长度和 state/retained 状态; - [已完成] MAIN-world 密码适配器注册表支持稳定 adapter 与运行时晚加载 adapter;
- [已完成] JSEncrypt RSA encrypt/decrypt/sign/verify 保留真实 receiver,并仅输出公私钥类型、位数和加盐指纹;
- [已完成] 为 CryptoJS 结果补充安全的字符串表示 evidence;
- [已完成] 从 exact link、请求字段和调用顺序生成只读候选;
- [已完成] Options / Yakit 展示置信度、证据和缺失步骤;
- [已完成] 候选结构可通过
browser.recording.get提供给 Agent。
P1:统一 Callable 与 Pipeline v2
- [已完成] 删除 recipe / adapter 双模型,不保留旧方法别名或迁移分支;
- [已完成] 页面 callable 使用统一注册表、来源信息、生命周期和命名 input slot schema;
- [已完成] Pipeline v2 使用有序 DAG,并加入类型化 context.read / builtin / page.call / output.write 节点;
- [已完成] builtin 限定为 JSON、文本、URL、Base64、Hex、对象和表单组合白名单;
- [已完成] 输出支持 body、字段级 body、header 和 query,并由 Yak 二次限制 URL 只能改变 query;
- [已完成] 单条 exact value link 且保留可执行调用句柄的 stateless/receiver 模式可直接编译候选;stateful/stream 模式必须捕获上层 callable;
- [已完成] 同一请求的多个密码来源合并为 request-level candidate,并强制捕获上层业务 callable 以保持动态值关系;
- [已完成] JSON 字段、表单字段、Header、Query 和完整 Body 会编译为对应的引导式输出,不要求用户理解 DAG;
- [已完成] 录制短时样本自动填入 Options/Yakit 明文网关本地回放,并允许编辑后恢复原样本;
- 为页面内回放生成确定性/结构性断言。
P2:自动业务函数捕获
- [已完成] 候选一键 arm,并在已有捕获等待或页面暂停时拒绝覆盖;
- [已完成] 业务 frame 使用来源、边界距离、函数可解析性、副作用、命名和作用域信息做确定性排序;
- 参数槽位与 request context 自动映射;
- 文档刷新后的引导式重新捕获。
P3:Yak AI Agent
browser_sessionattached resource;- task-bound 三个 Agent 工具;
- AIInferencePatch schema 与 Candidate Merger;
- Yakit 从候选直接启动带上下文的 AI 会话;
- Agent 操作写入现有 session timeline。
P4:复杂应用
- Axios/interceptor、GraphQL、WebSocket frame、protobuf 与自定义 serializer;
- [已完成] 按通用化路线迁移 adapter host,加入 sm-crypto、node-forge 与 Beacon/Worker/MessagePort 边界,并通过随机 ESM + WASM holdout;
- jsrsasign、jose 与后续现代密码生态按真实样本继续推进;
- sourcemap 存在时的业务 frame 增强;
- 多候选对比和跨操作共用 callable 识别。
P4 的实现顺序、协议草案、性能门禁和随机化测试矩阵以 FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md 为准。
16. 验收夹具
至少覆盖:
- 固定 CryptoJS AES,混淆变量名,JSON 字段输出;
- 真实 JSEncrypt RSA + form-urlencoded
data字段,独立服务端用私钥解密验收;保留实例 receiver,停止录制后对象明文仍可回放; - RSA 候选和 AI 上下文只包含 key 类型、位数与加盐指纹,不包含 PEM 或模数;
- WebCrypto AES-GCM + HMAC,闭包内不可导出 key 和动态 nonce/IV;
- AES + RSA + HMAC 同请求多来源图,不允许拆分低层调用回放;
- 动态 key promise,页面刷新后重新捕获;
- Axios interceptor 中的请求签名;
- Form URL encode 和 Header signature;
- 自定义业务 wrapper,低层库调用不足以构造完整报文;
- 未知函数与多个同分业务 frame,AI 只能补全候选,不能直接执行代码;
- WASM 导出函数,只能观察输入输出和业务 wrapper;
- 敏感预览开启时,AI payload、审计和诊断仍不含原始值;
- 500 事件 / 24,000 evidence 的性能与内存预算。
17. 目标目录
src/features/browser-recording/
evidence.ts
recorder.ts
src/features/browser-inference/
graph.ts
normalize.ts
rules/
candidates.ts
compiler.ts
ai-context.ts
src/features/browser-callable/
registry.ts
execute.ts
lifecycle.ts
src/features/browser-transform/
pipeline-v2.ts
profile.ts
replay.ts
Yak 侧将 browser_session 资源解析和 Agent 工具放在独立包中,依赖一个最小的 Bridge caller interface,避免 common/ai 直接依赖 gRPC Server。