先看结论与判断条件

  • 系统指令属于模型行为配置,不是访问控制;模型遵循指令也不等于调用者已经获得业务权限。
  • 把 Prompt 混淆、拆分或放进 Native 代码可以增加直接阅读成本,却不能让客户端持有内容变成可靠秘密。
  • 服务端 Prompt 模板应把模型配置、输入 schema、工具声明和正文作为一个版本化资产审查,但模板服务仍不是授权服务。
  • 长期凭据、角色判断、对象归属、额度和高风险工具执行必须留在服务端,客户端只持有当前会话所需的有限能力。
  • 工具调用采用明确 schema、服务端 allowlist、最小 scope、对象级授权、用户确认和审计,不能从 Prompt 文本推导权限。
  • 移动端加固属于纵深防御,可以保护商业实现并提高分析成本,但发布结论仍要建立在服务端控制和完整证据链上。

先区分行为指令和安全控制

系统 Prompt 的作用是向模型描述角色、语气、回答限制、工具使用偏好和上下文规则。它可以减少某些不符合预期的回答,却不负责证明调用者身份,也无法决定某个用户是否有权读取订单、修改配置或触发交易。安全边界需要稳定、确定、可审计地拒绝未授权请求,而生成模型的输出受到上下文、模型版本、输入内容和采样条件影响,两者的责任完全不同。

Firebase AI Logic system instructions 说明系统指令随请求影响模型行为,同时应用仍需控制输入、输出和工具权限。这个事实支持把 Prompt 视为行为层配置,而不是授权结论。即便模型回答“允许执行”,应用也必须忽略这句自然语言,依据当前会话、工具 schema、对象权限和服务端策略重新决策。模型回答可以成为用户界面建议,不能成为签名、令牌或权限凭证。

判断某项机制是否构成安全边界,可以问三个问题:攻击者能否观察或修改输入,拒绝结果是否由确定性代码产生,失败记录能否绑定具体策略版本。客户端内的 Prompt 很难同时满足这些条件。更合理的设计是让 Prompt 只产生结构化候选,由可信服务逐项验证,再返回范围有限、可撤销且可审计的操作结果。

系统 Prompt 与安全控制的责任对照
对象主要作用能否作为授权依据正确落点
系统 Prompt影响回答和工具选择倾向不能模型请求配置
输入 schema限制字段结构和类型不能单独授权客户端与服务端共同校验
会话认证确认当前主体提供身份基础可信服务端
对象授权判断主体能否操作资源可以形成拒绝决定业务服务端
工具策略限定可调用动作和 scope需与会话联合判断服务端策略层
用户确认让高风险影响对用户可见不能替代权限受控交互页面

移动客户端天然是公共环境

原生 App 的代码、资源和运行时状态都交付到用户设备。开发者可以通过编译、压缩、混淆和加固降低直接阅读与篡改的便利程度,但无法把客户端变成只有服务端才能观察的环境。系统 Prompt 若随应用包、资源、远端响应或运行时请求进入设备,就应按可能被看到和修改来设计。安全方案不能依赖攻击者永远找不到某段字符串。

RFC 8252 OAuth 2.0 for Native Apps 把原生应用视为公共客户端,推荐使用外部 user-agent 与 PKCE,而不是依赖客户端秘密。该原则虽然针对 OAuth 原生应用流程,却清楚表达了客户端秘密的边界:安装在用户设备上的应用无法可靠保守长期静态秘密。系统 Prompt 不是 OAuth 凭据,但若团队把其中的隐藏规则当成唯一授权条件,会犯同一种信任位置错误。

客户端可保存面向体验的默认 Prompt、离线提示和低风险格式说明,但必须假设这些内容会泄露、被替换或与服务器版本不一致。泄露后的结果应最多是别人知道产品如何组织回答,而不是获得 API 权限、访问客户数据或触发高风险工具。若 Prompt 暴露就会导致越权,说明真正需要保护的控制没有放在可信边界里。

移动端可保存与不应保存的内容
内容客户端可见后的影响推荐位置必要控制
回答语气与格式产品体验可被观察客户端默认值或服务端模板版本与回退记录
工具名称与参数说明接口形态可被了解客户端可持有公开 schema服务端 allowlist 和授权
长期 API 凭据可能被滥用调用服务服务端轮换、限权和审计
角色与对象权限被篡改会造成越权业务服务端按请求重新计算
客户敏感上下文泄露会扩大数据风险按需服务端检索最小化和访问控制
高风险动作批准伪造会改变业务状态服务端命令层用户确认、幂等和审计

隐藏、完整和服从是三件事

团队讨论系统 Prompt 安全时,经常把保密性、完整性和模型服从混在一起。保密性回答内容是否容易被读取,完整性回答当前请求使用的模板是否来自允许版本,模型服从回答输出是否符合指令。混淆或加密客户端资源主要影响静态读取成本,模板签名与版本门禁主要影响完整性,而模型服从仍受输入和模型行为影响。任何一项改善都不能替代另外两项。

如果业务需要保护 Prompt 中的商业表达,可以把主模板放在服务端,并只向通过认证的请求提供当前任务所需配置。即便如此,也应假设模型交互中有部分指令可被推断,日志或设备内存也可能出现可用表示。产品价值不应只依赖一句不可见文本,更不能把“不要调用管理工具”写在 Prompt 中后就省略工具权限检查。

完整性门禁应绑定模板 ID、模板版本、应用版本、模型配置、输入 schema、工具声明和回退值。应用收到远端模板后,要知道它适用于哪些候选、过期时如何处理、取回失败能否使用本地值。若本地回退允许的工具范围大于远端版本,网络故障可能反而放宽权限。正确策略是安全失败或使用更小能力的已知版本。

服务端模板也需要版本与回退治理

Firebase server prompt template syntax 说明服务端模板可以同时包含模型配置、system instructions、输入 schema、工具声明和模板正文。这些字段共同决定一次模型请求的行为,应作为同一配置资产评审和发布。只比较 Prompt 正文会遗漏温度、模型选择、工具定义或 schema 变化,导致报告与真实请求不一致。

Firebase server prompt templates get started 描述应用通过模板 ID 获取服务端配置。工程上需要建立 templateId、templateVersion、appVersion、modelId 和 fallbackVersion 的映射,并记录每次请求实际采用的版本。模板 ID 不应被理解成秘密,也不能直接代表“最新且安全”。服务端仍要验证调用者、应用版本和模板适用范围,并对下发失败提供明确状态。

远端配置可以缩短 Prompt 调整周期,但也增加发布治理责任。修改工具 schema 或系统指令可能改变可调用动作、字段含义和数据范围,应走与代码类似的审核、灰度和回滚流程。模板平台的语法和分发能力不保证模型行为稳定,也不替代业务授权。没有真实版本回执时,只能说明设计目标,不能宣称当前移动候选已经使用某份模板。

服务端 Prompt 模板的版本清单
字段需要绑定的对象变更影响放行证据
templateId 与版本模板正文和发布时间决定请求配置身份不可变版本记录
modelId 与参数目标模型和生成配置输出行为可能变化评审与灰度回执
system instructions角色、限制和回答要求改变行为边界差异审查
input schema允许输入字段与类型改变数据面正反输入用例
工具声明动作名称、参数和描述扩大可操作范围服务端 allowlist 对照
fallbackVersion网络失败时使用的配置可能改变能力和体验安全失败与回退测试

凭据和业务授权必须离开 Prompt

Android insecure API usage 指出移动客户端中的静态 API Key 可能被逆向或拦截,敏感服务应把长期凭据保留在服务端。系统 Prompt 更不应承载密钥、服务账号、内部令牌或“看到某句话就允许调用”的共享口令。自然语言字段缺乏专用凭据的轮换、受众、时效和使用审计,很容易进入日志、崩溃记录或调试界面。

把请求转到服务端并不自动完成安全设计。服务端代理仍要认证用户,限制允许模型、工具、数据域和额度,校验对象归属,并记录拒绝与异常调用。客户端可以获取短期、范围有限的会话能力,但不能拥有可跨用户、跨环境或长期使用的服务凭据。Prompt 中的角色描述如“你是管理员助手”只影响回答语气,不赋予请求管理员权限。

业务授权需要在工具真正执行前做最终判断。模型可以根据对话建议“读取发票”或“修改地址”,服务端必须把建议解析成明确命令,再依据当前主体、目标对象、动作 scope、对象状态和用户确认决定。任何来自 Prompt 或模型参数的 userId、role、isAdmin、price 和 approved 字段都属于不可信输入。

工具权限要用确定性策略收口

工具定义应当公开清晰,权限却不能写成模型自行解释的文字。服务端维护工具 allowlist,每个工具绑定参数 schema、最小 scope、对象授权函数、速率限制、幂等策略和确认等级。模型只选择候选工具并填写候选参数,执行器重新解析并校验。未登记工具、未知字段、重复参数和超出范围的值都应在进入业务处理器前失败。

工具返回的数据也要做最小化。模型不需要看到完成任务之外的字段,错误信息不应泄露内部权限结构或其他用户对象。服务端可以给模型返回稳定错误码和面向用户的安全摘要,把详细诊断留在受控日志。这样即使 Prompt 被观察或模型受到恶意输入影响,可到达的数据与动作仍由代码边界限制。

高风险工具需要用户确认,但确认不是授权替代。确认页面从服务端重新读取对象摘要和影响,不直接展示模型生成的事实;确认后提交一次性命令,服务端再次检查会话和状态。若对象在确认期间变化、会话切换或请求重复,幂等与状态门禁应拒绝或返回已有结果。Prompt 不能通过“用户已经同意”一句话跳过这一流程。

工具执行前的确定性门禁
门禁输入拒绝条件不能由谁决定
工具 allowlist候选工具名未知或当前场景未开放模型文本
参数 schema结构化候选参数未知字段、类型或范围错误Prompt 示例
会话认证访问令牌与设备状态失效、受众不符或风险异常客户端布尔值
对象授权当前主体、动作和资源无角色、无归属或状态不允许模型推断
用户确认服务端生成的动作摘要未确认或摘要已过期模型声称
幂等与审计操作标识和结果状态重复、过期或缺少审计上下文本地 Prompt

用扫描器发现被误当成秘密的配置

迁移第一步不是删除所有客户端 Prompt,而是识别哪些字段承担了不该承担的责任。扫描目标包括移动端 JSON、构建配置或资源清单中的 systemPrompt、hiddenPrompt、apiKey、secret、allowedRoles、authorizationRule、toolPolicy 和 privilegedTool 等字段。报告只输出字段路径、风险类别和迁移方向,不回显字段值,避免审计工具再次扩散敏感内容。

下面的 Python 脚本读取一份 JSON 配置,递归扫描键名,并区分行为配置、凭据、授权规则和工具权限。行为配置可以保留为公开默认值或迁移到版本化服务端模板;凭据必须移出客户端;授权规则和特权工具策略应迁移到可信服务端。脚本遇到非法结构会失败,发现高风险字段也返回非零状态,便于接入发布门禁。

字段名扫描只能发现显式问题,无法判断拼接字符串、压缩资源、Native 常量或运行时下发内容,也不能证明服务端代理已经正确认证和授权。它适合作为配置仓库的早期阻断,再配合构建产物检查、网络请求审计和服务端权限测试。扫描通过的结论只能写成“未发现这些已知字段”,不能写成“客户端没有任何秘密”。

扫描移动端配置中的 Prompt、凭据和授权规则字段
from pathlib import Path
import json
import sys

if len(sys.argv) != 2:
    raise SystemExit(2)
config_path = Path(sys.argv[1])
if not config_path.is_file():
    raise SystemExit(2)
try:
    document = json.loads(config_path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError):
    raise SystemExit(2)
if not isinstance(document, (dict, list)):
    raise SystemExit(2)
rules = {
    "systemprompt": ("behavior-config", "versioned server template or public client fallback"),
    "hiddenprompt": ("behavior-config", "versioned server template"),
    "apikey": ("credential", "server credential store"),
    "secret": ("credential", "server credential store"),
    "allowedroles": ("authorization", "server object authorization policy"),
    "authorizationrule": ("authorization", "server object authorization policy"),
    "toolpolicy": ("tool-permission", "server tool allowlist"),
    "privilegedtool": ("tool-permission", "server tool allowlist")
}
findings = []

def walk(value, path):
    if isinstance(value, dict):
        for key, child in value.items():
            normalized = "".join(character.lower() for character in str(key) if character.isalnum())
            if normalized in rules:
                category, destination = rules[normalized]
                findings.append({"path": path + [str(key)], "category": category, "destination": destination})
            walk(child, path + [str(key)])
    elif isinstance(value, list):
        for index, child in enumerate(value):
            walk(child, path + [str(index)])

walk(document, [])
summary = {"file": config_path.name, "findingCount": len(findings), "findings": findings}
print(json.dumps(summary, ensure_ascii=False, indent=2))
if any(item["category"] in {"credential", "authorization", "tool-permission"} for item in findings):
    raise SystemExit(3)

移动端加固是纵深防御,不是授权替身

OWASP MASVS-RESILIENCE 把抗篡改与抗逆向放在移动安全的纵深防御范围内。对包含商业 Prompt 编排、路由逻辑和端侧模型调用的应用,加固可以提高直接分析和修改成本,也能帮助保护核心实现。但它不能改变客户端属于公共环境的事实,更不能把客户端里的长期凭据或角色判断变成可信授权。

加固范围应围绕真正需要保护的商业代码和策略客户端实现,例如请求组装、响应校验、完整性信号采集与安全失败逻辑,同时把最终授权保留在服务端。若应用被修改,服务端仍能因为会话、对象权限、工具 allowlist 和幂等门禁拒绝危险操作。这样的分层设计才不会把全部安全压力放在一个隐藏 Prompt 或单一客户端检查上。

公开内容不能根据控制目录宣称某个候选已经达到防护强度。真实结论需要同一包体、同一签名、同一服务端策略和实际测试回执。本文只给出架构判断与配置扫描方法,不提供攻击阻断、性能、客户或排名数据。项目评审还要检查具体 Prompt 分发、日志、缓存、工具链和失败模式。

迁移时按责任移动,不按字符串搬家

发现隐藏 Prompt 后,不应简单把整段文本搬到服务器就宣布完成。先把内容拆成行为要求、输入 schema、工具描述、凭据、授权规则、数据检索范围和用户提示。行为要求与 schema 进入版本化模板,公开工具描述可以随客户端或模板维护,凭据进入服务端秘密管理,授权规则进入业务策略,敏感数据通过按请求检索和最小字段返回。

迁移验收需要覆盖正常、失败和回退。应用拿到正确模板时记录模板版本;拿不到模板时使用更小能力的本地默认值或安全失败;旧应用请求新模板时按兼容表处理;工具调用仍由服务端拒绝未知动作和无权对象。测试还要证明客户端修改 Prompt、伪造角色或直接调用工具接口不会改变服务端最终决定。

准备移动 AI 安全架构评估时,可整理客户端 Prompt 和配置清单、模板版本映射、模型与应用版本、工具 schema、服务端 allowlist、认证方式、对象授权、回退策略和拒绝用例,再通过御盾中央平台提交需求。核心目标不是让系统 Prompt 更难被看到,而是让它即使被看到或替换,也无法越过真正的凭据、权限和数据边界。

系统 Prompt 安全迁移验收表
迁移对象目标位置验证问题通过边界
行为说明版本化服务端模板版本、回退和适用应用是否绑定只影响模型行为
输入 schema模板与服务端校验器未知字段和类型错误是否拒绝不代表业务授权
长期凭据服务端秘密管理客户端包和日志是否不再持有服务端仍需限权
工具 allowlist服务端执行策略未知工具和超范围参数是否失败按当前会话判断
对象授权业务服务端伪造角色和对象 id 是否被拒绝绑定真实主体和状态
客户端加固应用候选核心实现和失败逻辑是否纳入评审属于纵深防御

事实依据与适用边界

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

本文判断事实或工程依据适用限制
系统指令影响模型行为,但应用仍需控制输入、输出和工具权限。Firebase AI Logic system instructions 描述 system instructions 的请求作用与应用控制责任。系统指令不能保证模型始终服从,也不能替代凭据、业务授权和工具执行门禁。
服务端 Prompt 模板可以同时包含模型配置、系统指令、输入 schema、工具声明和正文。Firebase server prompt template syntax 描述这些模板字段的结构和示例。模板语法和预览能力不保证模型行为稳定,也不提供业务授权。
应用通过模板 ID 获取服务端配置,需要管理模板、应用和回退版本关系。Firebase server prompt templates get started 描述模板获取与接入流程。模板下发不证明来源、适用版本、失败回退和当前候选已经正确治理。
移动客户端中的静态 API Key 可能被逆向或拦截,长期敏感凭据应保留在服务端。Android insecure API usage 描述不安全 API 使用和客户端静态密钥风险。服务端代理仍需认证、最小权限、额度、审计和滥用控制。
移动端抗逆向与抗篡改属于纵深防御控制。OWASP MASVS-RESILIENCE 给出移动应用韧性控制范围。控制目录不证明具体应用候选达到某种保护强度,也不替代服务端授权。
原生 App 属于公共客户端,不应依赖客户端秘密完成 OAuth 安全。RFC 8252 OAuth 2.0 for Native Apps 说明原生应用的公共客户端属性及外部 user-agent 与 PKCE 要求。RFC 8252 不定义移动 AI 工具的业务 scope、对象授权和授权时长。
系统 Prompt 即使完全泄露,也不应让调用者获得额外数据或工具权限。工程判断:行为配置与访问控制分离后,服务端仍会按当前主体、对象和动作拒绝未授权请求。是否达到该目标需要对真实客户端、服务端和工具接口做项目测试。
迁移系统 Prompt 时要按行为、schema、凭据、授权和工具策略拆分责任。工程判断:把整段文本原样搬到服务端会继续混淆配置分发与安全决策。本文不提供特定产品的实现、性能、攻击阻断或客户验证结论。

工程常见问题

把系统 Prompt 放进 Native 代码就能保密吗?

只能增加直接读取成本,不能让客户端成为可靠秘密存储。运行时仍需使用相关内容,安全设计应假设它可能被观察,并把凭据和授权放在服务端。

服务端下发 Prompt 后是否就形成安全边界?

没有。服务端下发改善配置治理,但模板仍只影响模型行为。调用者认证、工具 allowlist、对象权限和数据最小化需要独立实现。

Prompt 中写明只能管理员调用工具是否足够?

不足。模型对角色的描述不是授权证据。服务端必须从可信会话读取身份,并对具体动作和对象重新计算权限。

移动端是否可以保留本地系统 Prompt 作为离线回退?

可以保留低风险、能力更小的公开默认值,但要版本化并明确回退行为。离线 Prompt 不能包含长期凭据,也不能扩大工具或数据权限。

配置扫描器没有发现 secret 字段是否说明应用安全?

不能。扫描只能发现已知键名,还要检查构建产物、网络请求、日志、缓存和服务端授权。通过仅表示没有命中这组显式字段。

申请系统 Prompt 安全架构评估前要准备什么?

准备客户端配置、模板版本映射、工具 schema、服务端 allowlist、认证与对象授权、回退策略和拒绝用例,再通过御盾中央平台提交评估需求。

想用自己的 App 验证?

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

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