构建安全的 AI 系统

Securing AI systems

LLM 应用在沿用传统软件的身份管理、最小权限、输入输出校验与安全审计之外,还面临着生成式系统特有的新型失效模式,主要集中在以下三类问题:

  • 将不可信内容当作可执行指令:包括提示词注入(Prompt Injection)及其各类变体。
  • 不安全的输出处理:未经校验便将模型输出直接当作可信代码执行或作为合规依据转发。
  • 过度授予自主权限:赋予模型的工具调用、插件执行、网页浏览或数据检索能力超出了系统能够有效管控的边界。

OWASP 发布的 2025 年 LLM 应用十大风险(Top 10 for LLM Applications) 将核心威胁归纳为以下十项:

  • LLM01:Prompt Injection(提示词注入)
  • LLM02:Sensitive Information Disclosure(敏感信息泄露)
  • LLM03:Supply Chain(供应链风险)
  • LLM04:Data and Model Poisoning(数据与模型投毒)
  • LLM05:Improper Output Handling(不当输出处理)
  • LLM06:Excessive Agency(过度自主权限)
  • LLM07:System Prompt Leakage(系统提示词泄露)
  • LLM08:Vector and Embedding Weaknesses(向量与 embedding 相关弱点)
  • LLM09:Misinformation(错误与虚假信息)
  • LLM10:Unbounded Consumption(无限制资源消耗)

一个典型的生产级 LLM 系统至少横跨五道信任边界(Trust Boundaries):用户输入、外部检索内容、模型可调用的工具或 API、模型服务商(或自建推理服务),以及可观测性与存储系统。模型的输出与决策会直接影响这些边界,但应用层通常无法百分之百决定模型内部的行为。

攻击如何发生

直接与间接提示词注入(Direct & Indirect Prompt Injection):攻击者在用户提示词或外部数据(如邮件、文档、网页)中夹带恶意指令,诱导模型将其视为高优先级权威指令执行。其中,间接提示词注入潜伏在系统自动检索或读取的外部材料中,终端用户甚至完全看不到恶意载荷;一旦模型同时具备读取不可信外部内容与调用工具的权限,恶意片段就可能诱导模型窃取机密数据或越权调用工具。

RAG 知识库投毒(RAG Poisoning):攻击者将虚假事实或恶意指令混入检索语料库或上游数据源,诱导模型在生成回答时引用或遵从。哪怕只有极少数文档被污染,也可能导致特定话题下的定向错误回答,因此知识库摄取链路本身也是必须设防的攻击面。

不安全的输出处理:未经验证就渲染、执行或转发模型输出,可能引入 shell 或代码注入、政策绕过等传统漏洞。模型内容能够触发后续操作,因此在验证之前应视为不可信。模型可以大量生成看似可信且形式多变的字符串,将其直接用于代码、浏览器或自动化流程会扩大影响。

成本与可用性滥用(Denial of Wallet / Service):恶意攻击者或异常高频用户通过诱导超长输出、塞入超大上下文或触发海量并行检索,迅速消耗 token 预算并挤占共享配额,对其他正常租户造成拒绝服务(DoS)影响。

供应链风险(Supply Chain):风险贯穿基座模型权重、embedding 模型、推理引擎、向量数据库、训练/评测数据集以及安全护栏组件。无论是下载未经审计的模型权重与容器镜像、摄取来历不明的语料、在工具沙箱中运行未知代码,还是将密钥误写入可观测性日志,都可能引入供应链隐患。

隐私与数据保护风险:包括模型意外记忆并复述训练/上下文中的敏感信息、追踪日志明文留存个人身份信息(PII),以及外部模型服务商的数据留存策略。部署前必须明确“记录什么、发往何处、服务商保留多久”,并按合规要求配置数据生命周期。

用于分析风险的行业安全框架

OWASP Top 10 for LLM Applications:隶属于 OWASP GenAI Security Project(2025 版),覆盖 RAG 与智能体场景,为架构评审与威胁建模提供了直观的风险分类、攻击示例与缓解指南,便于研发与非安全背景人员对齐风险清单。

NIST AI Risk Management Framework(AI RMF 1.0):围绕 Govern(治理)、Map(映射)、Measure(测量)和 Manage(管理) 四个阶段组织 AI 风险管理,其配套的 Generative AI Profile 进一步细化了生成式 AI 在数据治理、防滥用与透明度上的控制要求,便于产品、法务与管理团队使用统一语言协同制定数据保留与应急响应策略。

Google Secure AI Framework(SAIF):强调将成熟的传统安全底座延伸至 AI 系统,覆盖模型、数据、处理流水线与运行环境的威胁检测、响应及自动化防护,帮助安全团队将 AI 应用纳入现有的安全运营(SecOps)与漏洞管理体系。

Guardrails:运行时安全防护措施

运行时护栏(Guardrails)部署在不可信输入、模型输出与敏感操作之间,用于限制系统允许接收、生成或执行的内容,与身份认证、最小权限控制及安全检索共同组成纵深防御体系。

1. 防护措施的三个分类维度

可以从三个方面分类。

  • 执行时间:生成前验证或转换提示及检索内容;生成中限制解码或工具调用;生成后在内容到达用户或工具前审核、遮盖、核查依据或阻止输出。
  • 确定性规则:正则表达式、JSON Schema 校验、上下文无关语法约束、黑白名单(Allowlist / Denylist)及策略引擎(易于预测和审计,但难以覆盖复杂的语义变体)。
  • 按部署位置划分:内嵌于应用 SDK / 业务服务层、集中部署在 API Gateway / Sidecar,或直接调用模型服务商托管的安全审核服务。

确定性措施较便于预测和审计,但覆盖范围有限;模型措施可以处理更难用规则表达的问题,却具有概率性,需要校准,也可能被绕过。尤其面对间接提示注入,需要多种措施配合。

2. 生产环境核心防护类别

输入与输出内容安全

内容风险分类在独立检测节点执行,可以使用自行部署的分类模型或经过核验的内容审核 API。每种服务支持的风险类别、语言、地域、错误策略和数据传输范围都需单独检查。内容审核的通过结果不会授予工具权限,执行端仍检查用户身份、目标资源和参数。

提示注入与越狱检测

提示词注入与越狱检测:专门识别试图覆盖系统指令或诱导非预期工具调用的恶意输入与检索片段(如引入 Microsoft Prompt Shields、Meta Llama Prompt Guard 2 等前置检测工具)。一旦检出异常,可立即拦截请求、清洗文本或临时禁用高风险工具。由于检测模型本质上仍是概率信号,必须配合工具层与输出层的硬性架构隔离,确保即便漏检也不会直接酿成安全事故。

结构化输出与约束解码

结构化输出与约束解码:当下游仅接受特定 JSON 或枚举值时,使用服务商原生支持的结构化输出能力配合 Pydantic 严格校验(课程贯通示例即采用百炼 schema 接口,并在解析后二次核验引用合法性与业务规则;本地 vLLM 等推理引擎也可按所用版本配置语法约束解码)。需将语法格式校验、内容事实判断与操作权限校验拆分为三个独立环节分别执行。

个人信息遮盖与敏感内容过滤

个人信息(PII)遮盖与敏感内容过滤:利用 PII 检测器与自定义正则规则,在用户提示词、检索片段、模型回答及工具返回结果中识别个人隐私数据或密钥凭据,并执行掩码遮盖(Masking)或拦截。在强监管场景下还应严格收敛可观测性日志范围(如默认禁止记录原始请求正文),并通过声明式策略在网关层统一执行脱敏。

依据核查与纠正

事实依据核查与纠正(Groundedness Check):将检索上下文与模型回答一同输入核查模型,实时评估回答是否严格受来源材料支撑(部分系统还支持高亮标出或改写无依据的陈述)。在 RAG 场景中这能有效压制胡编乱造,但前提是底层知识源本身的真实性已得到核验。

工具与网络出口防护

工具与网络出口防护:对工具调用与网络出站实施严格的确定性边界控制(同样独立于内容风险分类,内容审核通过不会授予工具权限,执行端仍必须逐一检查用户身份、目标资源与参数合法性)。

3. 实现模式与处置动作

应用内防护:在构建提示的服务中直接调用内容审核、注入检测和结构化输出。功能团队能够快速调整,但应使用共享库和默认策略,减少不同服务之间的规则差异。

Sidecar 或 gateway 防护:在应用代码之外统一实施内容审核、注入检查、schema 验证、PII 遮盖和网络出口允许列表。多个团队同时集成模型与工具时,这种方式便于集中管理和审计。

在执行层分别实现输入校验、业务授权、工具参数检查与网络出口限制。内容审核结果只作为一项检测信号;执行失败或结果未知时,应核查实际状态后再决定是否重试。

处理结果应明确,通常包括允许、阻止、转换或遮盖,以及转交人工。每条规则都应规定用户会看到什么,例如以下情况。

  • 检出提示词注入:立即阻断关联的工具调用,并返回预设的安全兜底回复。
  • 事实依据核查未通过:展示原始参考来源并标明置信度不足,或按风险等级直接拦截回答。
  • 检出个人敏感信息(PII):按策略遮盖脱敏后再继续后续处理。

云服务常返回结构化原因和分数,应将适当信息纳入遥测,以数据校准阈值。

后续步骤涉及代码执行或数据修改时,应使用 schema 或语法约束表达操作意图,并独立验证操作权限及参数。约束输出能够提高可控性,某些场景也能减少延迟。

保护检索器与外部访问边界:无论是抓取的公开网页还是多人共享的内部文档,均应视为不可信内容。需对读取到的外部内容执行注入检测,通过出站白名单限制允许访问的目标域名,并严禁工具访问未授权的内网主机名或云主机元数据端点(Metadata Endpoints)。

4. 阈值校准、遥测与红队测试

防护需要结合真实数据调整。内容安全和注入检测阈值应满足应用风险要求,记录原因与分数,并由产品及安全人员检查误报和漏报。追踪记录应标记策略版本,例如 vX.Y,以关联事件和策略变化。依据检查需要在评估集上测量阻止或标注是否减少错误,同时观察用户体验。还应运行红队测试,并随新攻击技术更新案例。

运维中可以尽量集中执行策略,通过 gateway 或 broker 统一调整规则、PII 模式和阈值。托管防护能够提供持续更新,但仍需记录判断和结果,以便解释阻止原因,并识别供应商更新后的回归。

分类器可能漏检,攻击方式也会持续变化。因此,代码化策略、出口允许列表、schema 或语法约束,以及严格的输出处理,对于涉及实际操作和内容渲染的路径尤为重要。依据核查只检查与来源的一致性;内容分类也无法覆盖全部业务风险,需要补充自定义规则和人工交接条件。防护本身会增加延迟和成本,低风险路径可以使用批量或异步检查,高风险操作则应在执行前同步验证。

应用示例

  • 基于内部文档的客户聊天助手:输入输出内容审核 + 检索片段间接注入检测 + 回答事实依据核查(标注或拦截)+ 结构化输出约束 + PII 自动遮盖。
  • 挂载工单、账单或邮件工具的智能体:工具执行前内容审核与注入检测 + 工具层独立权限策略与参数校验 + 受约束的操作意图结构化输出 + 网络出站域名白名单 + 单工具调用频次限额。
  • 支持公开网页浏览或链接抓取的助手:抓取内容注入扫描 + 封禁内网主机名与云元数据端点(防 SSRF)+ 阻断外部网页文本控制工具调用的通道 + 前端显式展示引用来源与置信度 + 严格限制单次检索扩展深度与 token 预算。

生产级 LLM 安全依赖清楚的边界和适当的自动化范围。将不可信输入中的指令与授权分开,执行操作前检查策略,验证输出,限制单个请求能够消耗的资源,防止遥测和缓存泄露,并持续使用真实对抗案例测试系统。

保护资料与执行权限

把认证、有效 ACL、租户过滤、输出 schema、引用检查、工具允许名单和网络出口分别实施。资料中的指令只作为文本。内容分类、提示注入检测、工具授权和事实核验是不同检查任务,应分别建立脱敏测试集;未知权限拒绝返回正文。

练习:记录本课所用配置、输入、预期结果与失败分支,并用脱敏数据复现。

使用内容审核 API 与独立执行策略

课程可选扩展示例接入阿里云 TextModerationPlus 服务(使用官方 alibabacloud_green20220302 SDK 并通过 RAM 身份完成签名,应用代码无需自行拼接底层云签名协议)。请求中的 ServiceParameters 为 JSON 字符串,输入审查与输出审查分别选用 llm_query_moderation 与 llm_response_moderation 服务标识;GREEN_ENDPOINT 与 RAM 访问凭据独立于大模型 API Key 单独配置。

examples/moderation.pyPython
import json
import os

from alibabacloud_green20220302.client import Client
from alibabacloud_green20220302 import models as green_models
from alibabacloud_tea_openapi import models as openapi_models
from alibabacloud_tea_util import models as util_models


def moderation_decision(body):
    if body.get('Code') != 200:
        raise RuntimeError(f"moderation_business_code={body.get('Code')}")
    data = body.get('Data')
    if not isinstance(data, dict):
        return 'hold'
    if data.get('RiskLevel') == 'none' and data.get('AttackLevel') == 'none' and data.get('SensitiveLevel') == 'S0':
        return 'allow'
    return 'hold'


def create_moderation_client():
    config = openapi_models.Config(access_key_id=os.environ['GREEN_ACCESS_KEY_ID'],
                                   access_key_secret=os.environ['GREEN_ACCESS_KEY_SECRET'])
    config.endpoint = os.environ['GREEN_ENDPOINT']
    return Client(config)


def moderate(client, content, data_id, output=False):
    if not content or not data_id:
        raise ValueError('moderation_input_invalid')
    request = green_models.TextModerationPlusRequest(
        service='llm_response_moderation' if output else 'llm_query_moderation',
        service_parameters=json.dumps({'content': content, 'dataId': data_id}, ensure_ascii=False))
    runtime = util_models.RuntimeOptions(connect_timeout=5000, read_timeout=10000, autoretry=False)
    response = client.text_moderation_plus_with_options(request, runtime)
    return moderation_decision(response.body.to_map())

本示例采用严格的默认拦截(Fail-closed / Hold)策略:仅当接口返回 Code == 200、且 RiskLevel == 'none'、AttackLevel == 'none'、SensitiveLevel == 'S0' 全部明确达标时才返回 'allow' 放行;一旦响应缺失字段或检出任何风险、攻击或敏感等级,一律返回 'hold' 进入待审核拦截状态;若发生接口超时、未授权或服务端报错,同样立即中断当前检查并保持待审核状态。

Green 服务和 RAM 权限由学习者在自己的授权环境配置,官方 SDK 处理签名;代码不自行实现云签名协议。审核可能向服务方传输文字,需要先核验资料使用权限和服务地域。本课程没有调用真实审核服务。

练习:使用官方 SDK 的真实请求/响应模型构造本地测试 fixture,分别覆盖全部无风险放行、缺失字段、业务错误码非 200、检出风险等级与检出攻击等级等分支;并验证任何审核放行结果都不会扩大下游工具的调用权限。

搜索课程

正在加载课程目录…