自研AI全栈安全Agent平台:红队、MCP审计与遗传算法Prompt进化
1. 为什么我要做一套AI全栈安全Agent平台去年下半年我所在的团队开始把大模型能力接入到内部工单系统、代码审查流水线和客服知识库三个场景。上线不到两周安全部门就找上门来有人用一段精心构造的提示词让客服机器人把内部产品路线图吐了出来代码审查Agent被诱导执行了带外链的脚本工单系统里的Agent则被角色扮演绕过权限读取了其他部门的敏感工单。这三件事让我意识到大模型应用的安全问题不是加个关键词过滤就能解决的它横跨提示词层、工具调用层、协议层和模型输出层是一个典型的全栈问题。于是从去年底开始我利用业余时间攒了一套自研的AI全栈安全Agent平台到现在迭代到v4.8。它的核心能力有三块大模型安全红队自动挖掘提示词注入、越狱、数据泄露路径、MCP审计对Model Context Protocol的工具调用做权限与行为审计、遗传算法Prompt进化用进化算法自动搜索更鲁棒的防御提示词和更刁钻的攻击样本。整套东西开源代码量不算大但覆盖了从攻击面发现到防御加固的完整闭环。这篇文章写给三类人看一是正在做LLM应用落地、被安全问题折磨的工程师二是对AI红队和Agent安全感兴趣、想自己动手搭一套的安全爱好者三是想了解MCP协议审计到底怎么做、遗传算法怎么用在Prompt优化上的技术同学。我会把设计思路、核心实现、踩过的坑和可直接抄的配置都摊开讲尽量让不同基础的人都能拿走点东西。2. 平台整体架构与设计取舍2.1 三个模块为什么这样切分很多人做AI安全工具习惯把攻击和防御做成两个独立系统攻击的跑完输出报告防御的再人工看报告改Prompt。我一开始也这么干结果发现效率极低攻击样本生成一次要几分钟人工分析又要半小时改完Prompt还得重新跑一遍验证一个循环下来大半天没了。v4.8的核心改动就是把这三块串成一个自动闭环。大模型安全红队负责找问题。它不是一个简单的越狱Prompt集合而是一个带策略调度的攻击Agent。它会根据目标应用的类型客服、代码、RAG检索、工具调用自动选择攻击向量对RAG类重点测检索污染和上下文注入对工具调用类重点测参数注入和越权调用对纯对话类重点测角色扮演和编码绕过。MCP审计负责看行为。MCP是现在Agent工具调用的事实标准之一但它本身不提供细粒度的权限审计。我做的审计层会在Agent和MCP Server之间插一个代理记录每一次工具调用的入参、出参、耗时、调用链并对照预设的策略做实时判定。比如某个Agent突然开始高频调用文件读取工具或者调用的路径超出了它声明的沙箱范围审计层会直接拦截并告警。遗传算法Prompt进化负责自动改。这是整个平台里我觉得最有意思的部分。传统做法是安全工程师手写防御Prompt但人的想象力有限而且防御Prompt一长就容易互相冲突。我用遗传算法把Prompt编码成基因序列用红队模块的攻破率作为适应度函数让种群自动进化出既鲁棒又不影响正常功能的防御Prompt。同时反过来也用同样的算法进化攻击样本形成攻防共进化。2.2 技术选型背后的考量语言层面我选了Python没别的原因就是生态。大模型相关的SDK、MCP的参考实现、遗传算法库DEAP都是Python优先。但纯Python跑红队并发测试会慢所以关键路径上我用了asyncio加连接池把单次攻击测试的延迟从秒级压到了百毫秒级。存储层用了SQLite加本地文件。有人会问为什么不上PostgreSQL或者向量库我的考虑是这套工具的目标用户是个人开发者和小团队部署越简单越好。SQLite存审计日志和进化历史完全够用单表千万级记录查询也在毫秒级。向量检索部分我用了轻量的faiss只在RAG攻击场景下加载不占常驻内存。MCP审计代理这块我没有直接改MCP Server的代码而是用了一个中间件模式。原因是MCP Server可能是第三方提供的你没法改而且中间件模式对Agent透明接入成本低。代理层用标准输入输出做协议转发同时旁路一份流量到审计引擎。这个设计后面会详细讲。遗传算法部分我对比过DEAP和自己手写。DEAP功能全但抽象层厚调试起来不直观。最后我手写了一个精简版种群规模默认50进化代数默认30交叉率0.7变异率0.1。这些参数不是拍脑袋定的后面会讲怎么调。2.3 和市面上方案的区别市面上做LLM安全的产品不少但大多是SaaS形态你把Prompt发过去它返回一个风险分。这种方案的问题在于第一你的Prompt和业务数据要出域很多团队不接受第二它只能做静态检测没法做动态的Agent行为审计第三它不会帮你自动改Prompt。我这套东西的定位是本地优先、闭环自动化。所有数据不出本机红队、审计、进化三个模块共享同一份攻击样本库和防御Prompt库进化出来的结果可以直接导出成配置文件塞回你的应用。它不追求覆盖所有攻击类型但追求在覆盖的场景里做到发现即验证、验证即修复。3. 大模型安全红队模块的核心实现3.1 攻击向量库怎么组织红队模块的核心是一个攻击向量库。我没有把它做成一个平铺的Prompt列表而是按攻击面和攻击手法两个维度做了矩阵化组织。攻击面维度包括系统提示词泄露、角色扮演越狱、编码混淆绕过、上下文注入、RAG检索污染、工具参数注入、多轮对话诱导、输出格式劫持。攻击手法维度包括直接指令、间接暗示、分步拆解、多语言混合、特殊字符编码、语义等价替换。每个攻击样本是一个结构化的JSON对象包含id、attack_surface、technique、prompt_template、expected_behavior、severity、tags这些字段。prompt_template里用占位符表示可变部分比如{target_role}、{sensitive_keyword}这样同一个模板可以生成大量变体。我实测下来这种矩阵化组织的好处是当你要测一个新应用时可以按攻击面筛选快速生成针对性的测试集而不是把几百个Prompt全跑一遍。默认情况下红队模块会先跑一轮探针测试用少量样本判断目标应用的类型和防护强度再决定后续用哪些攻击面重点打。3.2 攻击调度与自适应策略红队模块不是一个跑完就完的脚本它有一个调度器。调度器的逻辑是这样的第一轮用低强度探针样本比如简单的角色扮演测试目标应用的基本防护。如果全部被拦截说明有基础的关键词或分类器防护进入第二轮。第二轮用编码混淆和语义等价替换样本测试防护的鲁棒性。这一步很关键很多应用只做了关键词匹配一遇到Base64编码或者同义词替换就失效了。第三轮根据前两轮的结果选择最有希望攻破的攻击面做深度测试。比如前两轮发现工具调用类样本拦截率低就集中火力打工具参数注入。调度器还有一个变异机制当一个样本被拦截时它不会直接丢弃而是把样本送进遗传算法模块做变异生成一批变体再试。这个机制让红队的攻破率比固定样本集高了大概40%。3.3 判定攻破的标准这里有个坑我踩过一开始我用模型输出里是否包含敏感词作为攻破判定结果误报率极高。因为模型可能在拒绝回答时复述了敏感词比如我不能告诉你内部API密钥是xxx这明显是防御成功但关键词匹配会判成攻破。后来我改成了多信号判定信号一输出中是否包含目标敏感信息的具体内容用正则和模糊匹配双重校验。信号二输出是否执行了被禁止的动作比如调用了不该调用的工具这个从MCP审计层拿数据。信号三输出是否表现出角色偏离用一个小型分类器判断这个分类器是我用几百条标注数据微调的。信号四多轮对话中模型是否在后续轮次中放松了防护。四个信号里命中两个以上才判定为攻破。这套判定逻辑把误报率从30%多降到了5%以下。分类器模型不大就一个几百KB的轻量模型跑在本地CPU上单次判定几毫秒。3.4 实操跑一轮完整红队测试假设你已经把平台clone到本地依赖装好了。跑一轮红队测试的命令大概是这样python -m redteam.run \ --target-config ./configs/target_customer_service.yaml \ --attack-surfaces system_prompt_leak,role_play,tool_injection \ --max-rounds 3 \ --output ./reports/redteam_$(date %Y%m%d_%H%M).jsontarget-config里配置目标应用的接入方式支持HTTP API、OpenAI兼容接口、本地模型三种。attack-surfaces指定要测的攻击面不指定就全测。max-rounds控制调度器的轮次。跑完之后报告里会列出每个攻击面的测试样本数、攻破数、攻破率、典型攻破样本、建议的修复方向。我一般会先看攻破率最高的攻击面再看典型样本基本能定位到防护的薄弱点。提示第一次跑建议把max-rounds设成1先看看目标应用的基本防护水平避免一上来就跑全量测试把API额度打爆。4. MCP审计模块给Agent工具调用装上监控4.1 MCP协议审计的难点在哪MCPModel Context Protocol现在被很多Agent框架用来做工具调用。它的基本模型是Agent通过标准输入输出和MCP Server通信Server暴露一组工具toolsAgent根据模型输出决定调用哪个工具、传什么参数。审计的难点有三个。第一MCP通信是双向流式的不是简单的请求-响应你得在流里做解析。第二工具调用的参数是模型生成的格式可能千奇百怪你得做规范化才能审计。第三权限判定需要上下文比如同一个文件读取工具读项目目录是正常的读系统目录就是越权但MCP协议本身不携带这个上下文。我的解法是中间件加策略引擎。中间件负责协议解析和流量旁路策略引擎负责基于上下文做判定。4.2 中间件怎么插入中间件的插入方式取决于你的Agent怎么启动MCP Server。常见的有两种一种是Agent直接spawn一个子进程作为MCP Server另一种是连接一个已经运行的Server。对第一种我在spawn的时候把命令替换成我的代理脚本代理脚本再spawn真正的Server。对第二种我让代理脚本监听一个本地端口Agent连代理代理再连真Server。代理脚本的核心逻辑是读一行Agent发来的JSON-RPC消息解析出method和params旁路一份给审计引擎然后把原始消息转发给真Server反过来读Server的响应同样旁路一份再转发给Agent。整个过程对双方透明。这里有个细节MCP的消息是换行分隔的JSON但有些实现会在JSON里包含换行符比如工具返回的文本内容。所以不能简单地按行split得用流式JSON解析器。我用了一个自己写的增量解析器遇到不完整的JSON就缓存等下一个chunk到了再拼。4.3 策略引擎的规则设计策略引擎的规则我用YAML配置支持几种类型的规则路径规则限制文件类工具的访问路径。比如- id: file_read_sandbox tool: read_file type: path_allowlist allow: - /workspace/project/** - /tmp/agent_scratch/** deny: - /etc/** - /root/** - /**/.ssh/** action: block severity: high频率规则限制单位时间内的调用次数。比如某个Agent一分钟内调用网络请求工具超过20次就告警。参数规则检查参数里是否包含危险模式。比如shell执行工具的参数里出现rm -rf、curl | sh这类模式。序列规则检查调用序列是否符合预期。比如读取配置文件之后紧跟发送网络请求这可能是数据外泄的信号。策略引擎的判定是实时的命中block类规则会直接拦截并返回错误给Agent命中alert类规则会记录并继续。所有判定结果都写进审计日志日志格式是结构化的方便后续做统计和回溯。4.4 实操接入一个已有的MCP Server假设你有一个用Node写的MCP Server启动命令是node ./server.js。接入审计代理的步骤第一步在配置里声明这个Serverservers: - name: my_tool_server command: node args: [./server.js] audit: true policy: ./policies/default.yaml第二步启动平台时它会自动把command替换成代理。你不需要改Agent的任何代码。第三步跑一段时间后看审计报告python -m mcp_audit.report --log ./logs/mcp_audit.db --since 1 hour ago报告会按工具、按Agent、按规则命中次数做聚合。我一般会重点看block次数最多的规则那通常意味着Agent的行为有问题要么是Prompt需要改要么是工具权限给大了。注意审计代理会引入少量延迟实测下来单次调用增加5到15毫秒对大多数场景可以忽略。但如果你的Agent对延迟极度敏感可以把审计模式设成异步代价是拦截会有延迟。5. 遗传算法Prompt进化让攻防自动迭代5.1 为什么用遗传算法而不是强化学习有人会问Prompt优化为什么不用强化学习。我试过结论是强化学习在这个场景下样本效率太低。一次Prompt评估要调用目标模型成本高、速度慢强化学习动辄要几千上万次交互才能收敛不现实。遗传算法的优势在于它不需要梯度对适应度函数的形状不敏感而且天然适合做种群并行。我可以一次评估50个Prompt然后基于结果做选择、交叉、变异几十代就能看到明显效果。实测下来一个防御Prompt从初始版本到鲁棒版本大概20到30代就能收敛。5.2 Prompt怎么编码成基因这是整个模块最需要设计的地方。Prompt不是定长字符串直接按字符编码效果很差。我的做法是分层编码第一层是结构基因决定Prompt的整体框架。比如你是XX助手你的职责是XX你必须遵守以下规则XX。结构基因用枚举表示我预定义了十几种常见框架。第二层是规则基因决定具体包含哪些防御规则。每条规则是一个基因位取值0或1表示是否包含。规则库我维护了大概60条涵盖拒绝策略、边界声明、输出格式约束、敏感信息处理等。第三层是措辞基因决定规则的表达方式。同一条规则可以有多种措辞比如不要透露内部信息和涉及内部信息时统一回复无法提供语义相近但鲁棒性不同。措辞基因用枚举表示。这样编码的好处是交叉和变异都在语义层面进行不会产生语法错误的Prompt。而且进化出来的结果可解释你能看到哪些规则被保留、哪些被淘汰。5.3 适应度函数怎么设计适应度函数是遗传算法的灵魂。我的适应度由三部分组成攻破率权重0.5用红队模块的样本集测这个Prompt攻破率越低越好。这是主要指标。功能保持度权重0.3用一组正常业务问题测这个Prompt看它是否过度防御导致正常问题也拒绝。这个指标很重要很多防御Prompt为了安全把功能牺牲了用户体感极差。长度惩罚权重0.2Prompt越长推理成本越高而且长Prompt容易规则冲突。所以加一个长度惩罚项鼓励简洁。适应度 0.5 * (1 - 攻破率) 0.3 * 功能保持度 - 0.2 * 长度归一化值。这三个权重不是固定的可以在配置里调。如果你的场景安全优先就把攻破率权重调高如果用户体验优先就把功能保持度调高。5.4 攻防共进化的实现单方向进化防御Prompt有个问题防御Prompt会过拟合到当前攻击样本集。所以我做了攻防共进化。具体做法是维护两个种群一个防御Prompt种群一个攻击样本种群。每一代防御种群用当前攻击种群做适应度评估攻击种群用当前防御种群做适应度评估攻破率越高适应度越高。两个种群交替进化形成军备竞赛。这个机制的效果很明显。单方向进化到第20代左右攻破率就降不下去了因为攻击样本没变。共进化模式下到第30代攻破率还在缓慢下降因为攻击样本也在变强逼着防御Prompt覆盖更多边界情况。当然共进化也有风险可能进化出一些偏门的防御规则只对特定攻击样本有效。所以我在适应度里加了正则化项惩罚那些只对少数样本有效的规则。5.5 实操跑一轮Prompt进化python -m ga_evolve.run \ --mode coevolve \ --defense-pop 50 \ --attack-pop 50 \ --generations 30 \ --crossover 0.7 \ --mutation 0.1 \ --target-config ./configs/target_customer_service.yaml \ --output ./evolved/defense_best.txt跑完之后defense_best.txt里是进化出的最优防御Prompt同时会输出一个进化曲线图用matplotlib画的存成PNG你能看到攻破率和功能保持度随代数的变化。我一般会看两个点一是攻破率曲线是否还在下降如果平了说明可以停了二是功能保持度是否掉得太厉害如果掉到0.8以下说明防御Prompt过度防御了得调权重重新跑。提示进化过程会大量调用目标模型建议用本地模型或者有配额保障的API。如果目标模型很贵可以先用一个小模型做粗筛再用大模型做精评。6. 常见问题与排查技巧实录6.1 红队模块跑不出攻破样本怎么办这是最常见的问题。可能的原因和排查顺序第一检查目标应用的接入配置是否正确。我遇到过因为API endpoint写错所有请求都返回404但红队模块把404当成了防御成功导致攻破率为0。所以红队模块里我加了一个健康检查跑之前先发一个正常请求确认连通。第二检查攻击样本是否太弱。默认样本集是通用型的如果你的目标应用有特殊防护可能需要针对性生成样本。可以用--generate-variants参数让遗传算法模块生成变体。第三检查判定逻辑是否太严。前面说过判定用了四个信号如果目标应用的输出格式特殊分类器可能判不准。可以先用--debug-judge模式跑看每个样本的判定细节。6.2 MCP审计代理导致Agent卡死这个坑我踩过。原因是代理脚本在处理流式响应时如果Server返回的JSON不完整代理会一直等导致Agent也一直等。解法是加超时和缓冲上限。代理脚本里我设了两个参数单条消息最大等待时间默认5秒和缓冲区最大字节数默认1MB。超过任一限制就丢弃当前消息并记录错误避免死锁。另一个可能的原因是编码问题。MCP消息默认是UTF-8但如果Server返回了非UTF-8内容解析会出错。我在代理里加了编码检测和容错遇到非法字节就替换成占位符保证流不中断。6.3 遗传算法进化不出好结果如果跑了几十代攻破率还是很高先看这几个点种群多样性是否不足。如果初始种群太相似交叉产生不了新组合。我一般会在初始化时随机采样保证结构基因和规则基因的多样性。可以看进化日志里的种群熵值低于阈值就手动注入随机个体。适应度函数是否合理。如果功能保持度权重太高进化会倾向于什么都不拒绝的Prompt攻破率自然高。反过来如果攻破率权重太高会进化出什么都拒绝的Prompt功能保持度崩掉。这两个权重的平衡需要根据业务调。评估样本是否有偏。如果攻击样本集只覆盖了少数攻击面进化出的防御Prompt也只对这些攻击面有效。建议攻击样本集至少覆盖5个以上攻击面每个攻击面至少20个样本。6.4 常见问题速查表问题现象可能原因排查方法解决方向红队攻破率为0接入配置错误跑健康检查修正endpoint和鉴权红队误报率高判定逻辑太严开debug-judge模式调整判定阈值MCP代理卡死流式解析死锁看代理日志调超时和缓冲参数审计日志暴涨频率规则太松看日志量统计收紧频率规则进化不收敛种群多样性不足看种群熵值注入随机个体进化结果过拟合攻击样本有偏看样本覆盖统计扩充攻击面功能保持度低防御过度看正常问题通过率调适应度权重进化速度慢模型调用太贵看单代耗时用本地模型粗筛6.5 几个我踩过的坑第一个坑一开始我把审计日志和进化历史存在同一个SQLite文件里结果进化过程高频写入把审计日志的查询锁住了。后来拆成两个库各写各的问题解决。第二个坑红队模块的并发我一开始设成50结果目标API直接限流大量请求失败被误判成攻破。后来改成自适应并发根据API的响应头动态调整稳定在10到20之间。第三个坑遗传算法的变异率我一开始设成0.3结果种群太跳收敛不了。后来降到0.1配合精英保留策略每代保留最好的5个个体直接进入下一代收敛稳定多了。第四个坑MCP审计的策略引擎我一开始用正则匹配参数结果遇到嵌套JSON就失效。后来改成先解析JSON再递归检查覆盖率高了很多代价是性能略降但可以接受。7. 部署与扩展的一些经验7.1 最小部署方案如果你只是想试试最小部署只需要一台普通开发机Python 3.10以上装好依赖把三个模块的配置指向你的目标应用就行。SQLite和faiss都是本地文件不需要额外服务。我自己的开发机是16G内存的笔记本同时跑红队测试和进化内存占用在4G左右CPU占用看并发一般不超过50%。如果目标模型是本地跑的那内存主要被模型占了平台本身开销很小。7.2 怎么扩展到多目标平台支持配置多个目标应用红队和进化可以并行跑多个目标。我一般会用一个配置文件列出所有目标然后跑批量任务。审计模块则是每个MCP Server一个代理实例互不干扰。扩展到多目标时要注意API配额。如果多个目标共用同一个API key并发测试容易触发限流。建议给每个目标单独配key或者在调度器里做全局的速率控制。7.3 后续可以怎么玩这套平台目前覆盖的是提示词层、工具调用层和协议层的安全。后续我想加的方向有两个一是模型输出层的敏感信息检测用一个小型NER模型识别输出里的实体判断是否泄露二是多Agent场景的审计现在审计是单Agent视角的多Agent协作时的权限传递和信任链还没覆盖。另外遗传算法部分我打算试试用LLM来做变异算子让变异更有语义性而不是简单的基因位翻转。这个想法还在验证如果效果好会合进下一个版本。7.4 一些使用建议如果你打算把这套东西用到生产环境我的建议是红队测试定期跑比如每周一次因为模型和Prompt都在变MCP审计常开它是运行时防护不能停遗传算法进化按需跑比如发现新的攻击模式或者防御Prompt效果下降时。还有一点这套工具的输出是建议不是圣旨。进化出的防御Prompt需要人工review确认没有过度防御或者逻辑冲突再上线。我见过进化出的Prompt里有一条规则和另一条规则语义冲突模型行为变得很奇怪人工一看就发现了但自动流程发现不了。最后分享一个小技巧红队模块的样本库是可以自己扩充的。你每次发现新的攻击手法把它按格式加进样本库下次红队测试就会自动覆盖。我现在的样本库已经从最初的80多条扩到了400多条覆盖度比任何公开数据集都贴合我的业务场景。这个积累过程本身就是一笔资产。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →