先看结论与判断条件

  • 模型输出、system instructions 和工具声明都属于行为输入,不是服务端授权证据,任何调用都要经过独立策略判断。
  • 工具 schema 应固定版本、拒绝未知字段、约束参数类型和业务语义,并把解析后的规范对象送入授权层。
  • 用户确认必须绑定具体动作、关键参数、目标资源和有效上下文,通用的“我同意”不能覆盖后续任意调用。
  • 资源服务器要独立验证令牌 issuer、audience、expiry、client 与 scope,令牌可解析不等于当前业务动作获准。
  • DPoP 能降低被盗访问令牌的重放风险,但不能证明设备可信,也不能代替资源所有权和服务端业务规则。
  • 幂等键、资源版本和审计记录共同处理重复提交与竞态,移动端抗篡改仅作为纵深防御,不能承担当局授权。

先把模型建议与真实执行拆成两条链

移动 AI 应用常把搜索、下单、发消息、导出文件或修改配置封装成工具。模型根据对话生成工具名和参数,看起来像一个完整请求,但这只是候选动作。模型可能误解上下文,也可能受不可信内容影响,还可能生成超出当前用户权限的参数。服务端若把结构正确的工具调用直接执行,就等于把概率输出提升成业务授权。

Firebase AI Logic system instructions 说明 system instructions 会随请求影响模型行为,但应用仍要控制输入、输出和工具权限。系统指令适合表达角色、语气和任务约束,却不是不可绕过的安全边界。工程上应把模型阶段限制为产生意图,把执行阶段放到确定性的验证器中;验证器只接受白名单工具、规范参数、有效令牌和当前业务状态。

一条可审计链至少包含模型建议、schema 解析、用户确认、令牌校验、资源授权、幂等控制、真实执行和结果回写。每一步都保存独立状态,失败时返回明确但不过度泄露的错误。这样团队可以判断问题出在模型选错工具、客户端组装错误、令牌不足还是资源规则拒绝,而不是用一句“AI 调用失败”掩盖安全判断。

工具调用链各阶段承担的责任
阶段输入能证明什么不能证明什么
模型建议对话与工具描述模型选择了候选动作用户有权执行
Schema 解析工具名与参数结构符合当前契约业务状态允许
用户确认动作摘要与关键参数用户确认了特定展示内容令牌和资源权限有效
令牌校验access token 与证明调用方满足协议策略目标资源属于调用方
业务授权主体、资源、动作与状态当前请求可否执行模型输出必然正确

把工具 Schema 当作版本化安全契约

Firebase server prompt template syntax 展示服务端 Prompt 模板可同时定义模型配置、system instructions、输入 schema、工具声明和模板正文。这些字段会共同影响模型看到什么工具以及如何构造参数,因此应作为同一版本的配置资产审查。模板处于预览或发生版本变化时,更要保存发布版本、字段差异和回滚点,不能假设语法不变。

工具 schema 的第一道门是拒绝模糊输入。工具名使用稳定标识,参数对象禁止未知字段,字符串区分标识符与自由文本,枚举只接受明确成员,数量和时间等值要按业务语义解析。schema 验证后再生成规范对象,例如统一时区、去除重复项并解析资源标识。授权判断只读取规范对象,避免同一参数在展示、签名和执行环节产生不同解释。

schema 通过仍不等于允许执行。一个合法的 transferFunds 参数对象可能指向不属于当前用户的账户,一个合法的 exportDocument 请求可能读取受限制空间。工程判断是让 schema 回答“请求是否可理解”,让授权层回答“主体是否能在当前状态对该资源执行动作”。两种结果分别记录,禁止用解析成功覆盖权限拒绝。

工具 Schema 的关键防线
字段策略处理方式拒绝示例后续判断
工具名白名单匹配版本化注册表未知或停用工具进入该工具专属策略
拒绝未知字段只保留契约声明键附加管理员或 owner 字段防止参数走私
强类型与枚举先解析再规范化字符串冒充数量或状态生成确定性对象
资源标识按固定格式解析混合名称与内部标识查询真实资源属性
Schema 版本请求绑定注册表版本旧客户端调用已撤销字段选择迁移或拒绝

用户确认要绑定动作、参数与当前上下文

高影响工具通常需要用户确认,但确认页不能只显示模型生成的自然语言摘要。服务端应先规范化请求,再把工具标识、目标资源、关键参数、费用或不可逆后果等确认字段返回客户端。客户端展示这些确定字段,用户确认后提交与原请求绑定的确认标识。若模型在确认前后改变参数,原确认不应继续有效。

确认记录还要区分发起用户、当前会话和业务资源。共用设备、账号切换、应用恢复和并发窗口都可能让旧确认落到新上下文。工程判断是让确认标识绑定主体、规范请求摘要、资源版本和一次执行目的,并由服务端验证当前状态。这里不提供统一有效期,因为动作风险、交互时长和业务补偿能力各不相同。

低风险工具也不能把确认省略误解为授权省略。读取公开帮助内容可以采用较轻交互,但仍需 schema、令牌、资源和频率策略;发送消息、修改配置或产生费用的动作则需要更清晰的确认。产品可以按风险分级决定交互强度,服务端的业务授权始终保留,不能让客户端界面是否弹窗决定最终权限。

用户确认记录应绑定的对象
对象绑定内容失配风险处理方式
主体当前账号与客户端会话账号切换后复用重新确认
动作稳定工具标识和版本同一文案对应不同工具按工具策略核验
参数规范请求摘要确认后参数被替换摘要不一致即拒绝
资源资源标识与版本资源状态已改变重新读取并授权
后果费用、外发或不可逆说明用户未看到关键影响阻断高影响执行

资源服务器独立验证 Token 与 Scope

RFC 9068 JWT access token profile 说明 JWT access token 可携带 issuer、audience、expiry、scope 与 client 标识供资源服务器验证。工具服务不应只检查签名后读取 user id,还要确认令牌由认可 issuer 签发、audience 包含当前资源服务器、尚未过期、client 符合调用路径,并且 scope 覆盖当前工具动作。解析出声明只是开始,策略匹配才产生协议层结论。

scope 应表达可管理的协议权限,不能把全部业务状态塞进字符串。比如 document.write 可以说明令牌允许请求写文档,但文档是否属于当前组织、是否被锁定、当前用户在该空间是什么角色,仍由业务数据库和策略引擎判断。反过来,资源属于用户也不能弥补缺失 scope。两层都通过,调用才进入执行阶段。

RFC 9700 OAuth Security BCP 汇总重定向、令牌重放、授权码注入和不安全 grant 等部署风险。移动 AI 工具链应避免把长期高权限令牌交给模型上下文或日志,也不能让模型决定 OAuth 参数。令牌获取、刷新、存储和发送由受控客户端与协议组件承担,模型只看到执行所需的最小业务结果。安全 BCP 不决定具体商业角色,业务权限仍需项目策略定义。

访问令牌与业务授权的分层检查
检查数据来源失败含义通过后仍需检查
issuer令牌声明与信任配置签发方不被接受audience、有效期与签名策略
audience令牌声明与服务标识令牌不是发给当前服务scope 与业务资源
expiry令牌时间声明与服务时钟令牌不在有效窗口重放约束与会话状态
scope令牌声明与工具策略协议权限不足资源所有权和业务角色
client令牌声明与调用路径客户端不符合策略主体、资源和动作关系

DPoP 降低令牌重放,但不证明设备可信

RFC 9449 OAuth DPoP 定义用客户端持有密钥生成证明,并把访问令牌约束到对应密钥的机制。资源服务器验证 DPoP proof 与请求方法、目标地址、时间和令牌关联后,可以降低被盗 bearer token 被其他持有者直接重放的风险。对于能触发真实业务动作的 AI 工具,这是一项有价值的协议层约束。

DPoP 不是设备证明。持有密钥的客户端仍可能运行在被控制的环境,应用逻辑也可能被修改;密钥绑定更不能回答用户是否拥有目标资源。服务端仍需验证 scope、主体、资源、业务状态和确认记录,并采用合适的令牌有效期与撤销策略。把 DPoP 验证成功写成“设备可信”会扩大规范结论。

实现时还要处理 proof 唯一标识、时间偏差、服务端 nonce、目标地址规范化和代理转发边界。若网关负责校验,后端必须获得不可伪造且边界清晰的校验结果,不能信任客户端自报。工程判断是把 DPoP 结果作为授权输入之一,并保存失败类别,但日志中不记录完整访问令牌、私钥或可直接重放的敏感材料。

  • DPoP proof 与当前 HTTP 方法和目标地址匹配
  • 访问令牌确认绑定到证明密钥
  • 唯一标识和时间策略处理重复证明
  • 网关到后端的校验结果具有可信边界
  • DPoP 通过后继续检查 scope 与资源授权
  • 日志不保存令牌、私钥或完整证明载荷

资源所有权、业务状态与幂等必须一起判断

工具服务拿到有效主体后,应从服务端数据读取目标资源,而不是接受客户端传入的 owner 字段。策略输入至少包含主体、组织、资源真实所有者、角色、动作、资源状态和工具版本。跨租户资源要先确定租户边界,再判断角色权限;软删除、冻结、审批中或版本冲突的资源,即使所有者相同也可能不能执行当前动作。

AI 工具调用容易因网络恢复、流式响应中断、客户端重试或模型重复建议而多次提交。幂等键应由受控应用生成并绑定主体、工具和规范请求摘要,服务端保存首次结果。相同键配相同摘要可以返回原结果,相同键配不同摘要必须拒绝。幂等控制避免重复副作用,但不能把第一次未授权的请求变成已授权。

竞态还要求资源版本参与决策。用户确认时看到的文档、订单或配置,执行前可能已被其他流程修改。服务端可比较确认记录中的资源版本和当前版本,失配时重新展示或要求业务冲突处理。工程判断是让授权和写入位于同一受控事务边界,避免授权检查后到实际更新前状态发生变化。

服务端业务授权的最小输入
输入可信来源典型拒绝原因审计记录
主体与组织已验证令牌和服务端会话主体不在目标租户主体、client 与组织标识
资源所有者服务端资源存储客户端声明与真实归属不同资源标识和真实 owner
动作与参数规范化工具请求动作超出角色或参数边界工具版本与请求摘要
资源状态当前数据库记录冻结、删除或版本冲突状态和版本快照
幂等键受控客户端与服务端记录同键对应不同请求首次结果与重放判定

移动端防护只做纵深防御,不接管授权

OWASP MASVS-RESILIENCE 把抗篡改与抗逆向放在移动应用纵深防御中。对 AI 工具调用而言,客户端保护可以增加修改工具注册表、替换确认界面或窃取集成逻辑的成本,也有助于保护发布候选的完整性。但控制目录本身不证明某个候选包达到任何强度,更不能让服务端跳过权限检查。

所有安全关键字段都应假设客户端可能被观察或修改。owner、价格、角色、scope、确认状态和幂等结果不能以客户端自报为准;客户端传来的 schema 版本也要在服务端注册表中解析。移动端可以持有短期凭据和生成协议证明,却不应包含能够授予任意业务权限的静态秘密或本地管理员开关。

发布验收需要把客户端与服务端分别留证。客户端侧记录候选摘要、签名身份、工具注册表版本和关键交互回归;服务端侧记录令牌策略、schema 注册表、资源授权测试、幂等与审计结果。项目证据尚未接入时,只能说明设计门禁和待验证项,不能声称攻击阻断、兼容通过或统一性能结果。

客户端与服务端控制的合理边界
控制客户端职责服务端职责错误做法
工具注册展示受支持动作维护权威 schema 与版本客户端声明新工具即接受
用户确认展示规范动作和后果绑定确认与请求摘要只信任本地确认布尔值
令牌安全获取和发送验证签名、声明与 scope把高权限令牌放进模型上下文
资源授权提交资源标识读取真实归属与状态接受客户端 owner 字段
应用防护提高篡改与分析成本始终执行独立授权加固后关闭服务端校验

用只读校验器固定发布前的授权输入

下面的 Python 示例读取策略文件和待审计调用文件,只做离线校验,不访问业务系统。策略定义工具允许字段、必需 scope 和资源所有者;调用文件包含工具名、参数、令牌 scope、主体、资源 owner 与幂等键。脚本拒绝未知工具、字段走私、scope 不足、owner 失配和无效幂等键,并输出规范摘要供审计。

示例把工具 schema、scope、owner 和幂等键放在同一检查器里,是为了展示数据如何汇合,不代表生产系统应依赖一个本地 JSON 文件。真实服务要从可信令牌验证器、schema 注册表和资源数据库获得这些值,并在写入事务中重新判断。客户端提交的 tokenScopes 或 resourceOwner 不能直接成为可信事实。

发布门禁应同时覆盖允许路径和拒绝路径,包括未知字段、缺 scope、跨资源、相同幂等键不同摘要、确认过期和资源版本变化。准备移动 AI 应用加固评估时,可整理真实候选、工具注册表、服务端授权策略、令牌架构、关键动作清单和回归范围,再通过御盾中央平台提交申请。评估结论必须绑定实际材料,不能用模型提示词替代授权证据。

  • 模型输出只生成候选动作,不生成授权结论
  • 服务端按版本化 schema 拒绝未知字段
  • 令牌 issuer、audience、expiry、client 与 scope 分别验证
  • 资源 owner 和状态从服务端可信存储读取
  • 确认记录与规范请求摘要及资源版本绑定
  • 幂等键相同但请求摘要不同必须拒绝
  • 移动端防护不替代任何服务端授权门禁
校验工具 Schema、Scope、Owner 与幂等键的只读脚本
from pathlib import Path
import hashlib
import json
import re
import sys

if len(sys.argv) != 3:
    raise SystemExit(2)
policy_path = Path(sys.argv[1])
call_path = Path(sys.argv[2])
if not policy_path.is_file() or not call_path.is_file():
    raise SystemExit(2)
policy = json.loads(policy_path.read_text(encoding="utf-8"))
call = json.loads(call_path.read_text(encoding="utf-8"))
tool_name = str(call.get("tool", ""))
tool_policy = policy.get("tools", {}).get(tool_name)
if not isinstance(tool_policy, dict):
    raise SystemExit(2)
arguments = call.get("arguments", {})
if not isinstance(arguments, dict):
    raise SystemExit(2)
allowed_fields = set(tool_policy.get("allowedFields", []))
required_fields = set(tool_policy.get("requiredFields", []))
argument_fields = set(arguments)
if not argument_fields.issubset(allowed_fields) or not required_fields.issubset(argument_fields):
    raise SystemExit(2)
token_scopes = set(call.get("tokenScopes", []))
required_scopes = set(tool_policy.get("requiredScopes", []))
if not required_scopes.issubset(token_scopes):
    raise SystemExit(2)
subject = str(call.get("subject", ""))
resource_owner = str(call.get("resourceOwner", ""))
if not subject or subject != resource_owner:
    raise SystemExit(2)
idempotency_key = str(call.get("idempotencyKey", ""))
if re.fullmatch(r"[A-Za-z0-9._:]{16,128}", idempotency_key) is None:
    raise SystemExit(2)
canonical = json.dumps({"tool": tool_name, "arguments": arguments, "subject": subject}, sort_keys=True, separators=(",", ":"))
request_digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()
result = {"status": "eligible-for-server-authorization", "tool": tool_name, "requestDigest": request_digest, "idempotencyKey": idempotency_key}
print(json.dumps(result, ensure_ascii=False, indent=2))

事实依据与适用边界

以下内容区分官方事实、本文工程判断和不能外推的范围,避免把设计建议写成未经验证的产品结论。

本文判断事实或工程依据适用限制
服务端 Prompt 模板可以组合模型配置、system instructions、输入 schema、工具声明和模板正文。Firebase server prompt template syntax 展示这些字段的模板语法与配置关系。模板能力存在预览期限制,语法正确不保证模型稳定,也不替代客户端和服务端授权。
system instructions 会影响模型行为,但应用仍需控制输入、输出和工具权限。Firebase AI Logic system instructions 说明系统指令的作用方式与应用侧控制责任。系统指令不能完全阻止泄露、越权或意外输出,不能被当成授权边界。
OAuth 部署需要处理令牌重放、授权码注入、重定向与不安全 grant 等风险。RFC 9700 OAuth Security BCP 汇总 OAuth 部署的安全建议与已知攻击面。该 BCP 不定义具体 AI 工具的商业角色、资源所有权或动作权限。
JWT access token 可携带 issuer、audience、expiry、scope 和 client 标识供资源服务器验证。RFC 9068 JWT access token profile 定义面向 OAuth 资源访问的 JWT 声明配置。JWT 格式不保证签发策略正确、令牌足够短命或业务资源已经授权。
DPoP 可以把 access token 约束到客户端持有的密钥并降低被盗令牌重放风险。RFC 9449 OAuth DPoP 定义 proof 与访问令牌的发送者约束机制。DPoP 不证明设备可信,也不替代 scope、资源所有权、短有效期和业务授权。
移动端抗篡改与抗逆向属于纵深防御,不应承担服务端授权职责。OWASP MASVS-RESILIENCE 把相关控制放在移动应用韧性与纵深防御范围。控制目录不证明某个候选包的防护强度,也不支持关闭服务端权限检查。
工具 schema 通过只说明请求可理解,不能说明主体有权执行动作。工程判断:结构验证与主体、资源、动作、状态的授权判断回答不同问题。具体角色、资源状态和确认规则必须由项目业务策略与真实数据确定。
幂等键应绑定主体、工具与规范请求摘要,相同键配不同请求必须拒绝。工程判断:这种绑定能区分合法重试与参数被替换的重复提交。幂等控制不授予权限,也不能替代事务、资源版本和业务补偿设计。

工程常见问题

工具调用已经符合 JSON Schema,为什么服务端还要鉴权?

Schema 只证明工具名和参数可以被理解,不证明令牌 scope 足够、资源属于当前主体、业务状态允许或用户确认仍有效。服务端必须用规范请求重新执行这些判断。

在 system instructions 中写明禁止越权,能否代替权限校验?

不能。system instructions 会影响模型行为,但不是不可绕过的安全边界。模型只能建议动作,真实工具服务仍要验证令牌、资源、动作和当前业务状态。

JWT 签名验证通过,是否就能执行 AI 工具?

不能。还要验证 issuer、audience、expiry、client 与 scope,再从服务端读取资源所有者、角色和状态。JWT 格式和有效签名都不能自动授予具体业务权限。

使用 DPoP 后还需要短期令牌和资源授权吗?

需要。DPoP 主要降低被盗 bearer token 被其他持有者重放的风险,不证明设备可信,也不说明调用者有权修改目标资源。

用户已经点击确认,为什么同一请求仍可能被拒绝?

确认可能与当前主体、参数或资源版本不一致,令牌也可能过期或 scope 不足。确认是授权输入之一,服务端要在执行时重新核对完整上下文。

移动 AI 工具链申请加固评估前要准备什么?

准备真实候选包、工具 schema 注册表、关键动作与确认流程、令牌架构、服务端资源授权规则、幂等策略和目标回归范围,再通过御盾中央平台提交申请。

想用自己的 App 验证?

提交候选包、目标系统和关键业务路径,申请御盾 PoC 与兼容性评估。

继续阅读: 移动 AI 应用的运行时安全边界