直接回答
本地模型输出应在进入每个具体使用位置之前按不可信输入处理。一个值能安全显示为纯文本,并不表示它可以放进 HTML 属性、导航链接、文件路径或平台操作参数。先列出屏幕、链接、通知、分享和工具调用等实际使用位置,再为每个位置确定允许的数据、解释方式、编码规则和拒绝行为。这里讨论的是输出进入应用功能的边界,不能用一套删除敏感词的规则覆盖全部场景,也不能把本地生成当成可信来源。 结构校验、展示处理和授权是三个独立阶段。JSON 解析及 schema 校验只回答字段和类型是否符合约定;上下文编码回答某个字段如何交给渲染器;授权回答当前用户、任务状态和权限是否允许执行特定操作。任意一项通过,都不能代替另外两项,更不能证明生成内容正确。应用应自行构造固定操作,只接收预先定义的参数,不能直接将模型返回的整段对象映射成具有权限的操作对象。 展示普通文字时,优先使用不会解释标记的文本组件。在 WebView 内的网页中,可以把文字赋给目标 DOM 节点的 textContent,而不是拼接 HTML;这是网页 DOM 的用法,不是一个名为 setText 的 WebView 原生接口。如果确实需要富文本,应使用维护中的、适合当前格式的清理器,限制允许的标记,并为 HTML 正文、属性和 URL 分别选择正确的编码。删除尖括号或用单一正则替换并不能建立完整的安全边界。也不要让文字里的链接在用户未选择时自动导航。 导航前先把地址解析为 URI,再核对实际 scheme、host 和功能允许的目标。Android 的不安全 URI 加载文档指出,遗漏协议检查或用 startsWith、contains 等方法部分匹配主机名会形成错误信任。处理域名、编码字符和不透明 URI 时,应采用明确的允许规则;不符合规则就保留为文字或显示可恢复错误。验证后的地址也只能用于被授权的导航流程,不能因此扩大它可以访问的应用组件或内容范围。 平台操作须由应用控制。不能把模型文字当作序列化 Intent 后直接启动,也不能让输出任意指定组件、动作、flags、嵌套 Intent 或内容 URI。应用选择固定目标,再复制它允许的有限字段;必要时仍须核对用户确认和当前权限。文件名也不能直接拼接在存储根路径上,应通过应用控制的标识和目录规则定位,并阻止路径逃逸。用户选择的文档应继续使用选择器给出的 URI 和授权,而不是从生成文字重建文件路径。 诊断应独立处理。日志通常只需要请求标识、阶段、构建版本和受限错误类别,不应序列化完整模型响应、提示词或文档。即使文字可显示给用户,也不代表它可写入公开诊断或分享包。需要排查问题时使用合成 canary 值,分别检查正常路径、解析错误、导航拒绝和平台调用失败,确认它们不会进入不应接收内容的日志。用户主动提交支持报告时,应预览实际字段,不能自动附带整段会话。 为每个边界写明成功、拒绝和不可观察的结果。准备带标记、控制字符、双向文字、长字符串、编码域名、路径分隔符和不支持结构的合成样例;检查文字是否被按文本显示、导航是否被正确阻止、操作是否只使用应用拥有的字段。验证结果仅限受测实现。输出处理不会保证模型答案真实、不会替代授权,也不能被宣传为完全消除提示注入或所有隐私风险。
生成的建议同时带有链接和导出文件名
应用准备显示一段本地模型建议,建议包含看起来像 HTML 的文字、导航地址和拟定的导出文件名。JSON 结构合法,但这些字段即将进入不同的渲染与平台接口,开发者需要决定哪些可显示、哪些必须拒绝、哪些需要用户确认。
决策
分别定义纯文本、URI、应用控制的文件位置和固定平台动作边界,逐项验证;不使用一个通用清理函数代替所有检查。
预期结果
文字被按预期方式显示,不可信地址和路径不会触发越界操作,失败状态可重试,并且诊断只保留必要类别。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- FUNCTION-01:生成的函数提案不等于动作授权。
- COVE-LIFECYCLE-01:任务状态和执行所有者须明确。
- Android、MDN 与 OWASP 的具体输出边界文档。
任务质量需要有版本记录的语料和验收规则;流畅的单条样例不等于准确度结果。
实施流程
- 列出实际使用位置. 从模型响应沿数据路径追踪至纯文本组件、WebView DOM、链接、文件和平台操作。为每项写明允许字段、解释方式和用户可见目的,删去没有用途的字段。
- 按展示上下文处理. 普通文字通过纯文本组件或 DOM textContent 展示。需要富文本时使用适合格式的受限清理器,再按正文、属性和地址上下文编码;不要将一套转义规则用于所有位置。
- 验证 URI 和路径. 先解析 URI,再匹配允许的协议和实际主机名;拒绝模糊或不支持形式。文件位置由应用控制的标识和目录解析,文档选择保留原 URI 授权,不拼接生成的路径。
- 构造固定平台操作. 由应用确定组件、动作和允许的参数,仅复制约定字段。检查权限、任务身份与用户确认,不把生成的嵌套 Intent、flags 或操作对象直接传入平台。
- 用合成样例测试拒绝分支. 覆盖标记文字、编码地址、路径分隔符、控制字符、长文本和未知结构。核对显示、阻止导航、操作参数及恢复状态,并检查合成 canary 未进入不该接收内容的日志。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- 纯文本、标记、URI、路径和平台操作各有明确规则,结构校验不被当作执行许可。
- 未通过目标和权限检查的字段不会触发导航、文件访问或平台操作。
- 拒绝状态可恢复,正常及异常路径的诊断不附带完整私有内容。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| 结构校验 | 检查字段、类型和长度 | 能确定是否符合数据契约,不能保证含义正确、展示安全或动作已获许可。 |
| 上下文编码 | 为具体渲染位置处理文字 | 纯文本、HTML 属性和 URL 需要不同规则,一处合格不能用于所有解释器。 |
| 目标与授权检查 | 由应用构造固定动作 | 只允许当前流程、权限和用户选择范围内的操作,生成提案不能自行取得权限。 |
需要避免的失败模式
- 把通用脱敏函数用于所有展示与执行场景。
- 仅检查地址字符串中是否包含可信域名。
- 把成功解析或用户看过文字当作操作授权。
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- FunctionGemma mobile actions
- Android 文档:WebView URI validation
- Android 文档:Intent redirection
- MDN:用 textContent 显示纯文本
- OWASP:按上下文进行输出编码
- Android 文档:log information disclosure
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
一个通用脱敏函数能处理所有模型输出吗?
不能。敏感字段删减、HTML 编码、URI 验证和动作授权回答的是不同问题。应为每个实际使用位置建立规则;文字能展示并不代表它可以用于导航或平台调用。
JSON 已解析成功,为什么仍要检查链接和路径?
解析只确认数据结构,不能确认地址指向可信目标或路径留在应用拥有的范围内。还需核对解析后的协议、主机、目录规则和用户许可,并保留明确拒绝分支。
通过输出处理测试后能宣称完全安全或不会泄露吗?
不能。测试只覆盖选定实现、样例与可观察路径,不能证明所有生成内容都安全。需分别审核日志、分享、授权及其他数据路径,也不能把清理后的文字当成事实正确的证据。