最近几天集中把剩余的高优先级Bug清理了一遍,主要是三个方向的工作:多智能体协作加了反馈循环机制、前端修了XSS漏洞、后端补了限流和类型一致性
一、开发目标
- 为多智能体协作流程增加CriticAgent反馈循环,让SQL生成质量可迭代提升
- 修复前端chat.js的XSS注入风险
- 为AuthController添加IP限流保护
- 修正SqlAuditLog的userId类型与其他实体保持一致
- 排查QueryHistoryRepository的findAll()暴露风险
二、核心开发工作
2.1 多智能体循环迭代机制
之前的多智能体协作是单向流水线:规划→检索→生成SQL→批判→执行。CriticAgent审查完SQL之后,不管发现什么问题,审查结果都被直接丢掉了,ActionAgent拿到的是未修正的SQL直接去执行。说白了CriticAgent白干了。
这次在AgentOrchestrator里加了一个循环逻辑。CriticAgent审查完之后,如果发现SQL有问题,就把问题反馈回来重新生成SQL,然后再审查,直到通过或者达到最大迭代次数。具体来说:
- 新增
MAX_CRITIC_ITERATIONS = 3常量,最多循环3轮,防止无限迭代 - 阶段4从单向执行改为循环:Critic审查→发现问题→用反馈重新生成→再审查→通过后执行
generateSqlWithLLM()新增correctionFeedback参数,首次生成时传null,修正时传入Critic的反馈- 新增
buildSqlCorrectionPrompt()方法,把Critic的问题描述注入到修正prompt里
改完之后的流程变成了:生成SQL→Critic审查→有问题就带着反馈重新生成→再审查→最多3轮→通过后执行。CriticAgent终于不是摆设了。
2.2 前端XSS修复
chat.js里渲染消息时用的是innerHTML,如果LLM返回的内容里夹带了恶意HTML或JS代码,就会被直接插入到页面里执行。虽然正常使用不太可能触发,但作为安全漏洞必须堵上。
修复方式是加强escapeHtml()函数,原来只转义了&<>三个字符,现在补上了"和',防止通过HTML属性注入。然后排查了chat.js里所有使用innerHTML的位置,确认每个地方拼入的外部数据都经过了escapeHtml转义。一共排查了5处innerHTML使用,全部安全。
2.3 AuthController IP限流
登录和注册接口之前没有任何限流保护,攻击者可以暴力破解密码或者批量注册账号。这次加了一个基于IP的内存限流器:
- 用ConcurrentHashMap存储每个IP的请求计数和首次请求时间
- 1分钟时间窗口内,同一个IP最多允许5次请求
- 超过限制直接返回429状态码和提示信息
- 定时清理过期的计数记录,避免内存泄漏
2.4 SqlAuditLog类型修正
SqlAuditLog实体的userId字段是String类型,但其他所有实体(QueryHistory、AgentMemory等)的userId都是Long类型。类型不一致早晚要出问题,这次统一改成了Long。
改动涉及面比预期大一些:SqlAuditLog字段改了之后,SqlAuditService的buildAuditLog方法和三个公开日志方法的参数类型都要跟着改,SqlSecurityAuditAspect里的userId变量也要从String改成Long。改动本身不难,就是涉及文件多,要确保每个调用方都改到位。
2.5 QueryHistoryRepository暴露排查
这个Bug说QueryHistoryRepository继承了JpaRepository,默认暴露了findAll()方法,如果误调用会返回所有用户的历史记录。排查了一遍整个项目的代码,没有任何地方调用过findAll(),所有查询都是按userId过滤的。所以这个风险目前是理论上的,不需要改代码,确认安全就行。
三、关键实现细节
循环迭代的终止条件设计
最多3轮的限制是经过考虑的。每轮迭代都要调一次LLM,3轮就是额外的2次LLM调用(首次生成不算迭代)。如果CriticAgent连3轮都审不过,说明要么是用户的问题太模糊,要么是schema信息不够,继续迭代也不会有改善。超过3轮就直接用最后一次的结果执行,把审查结果展示给用户参考。
IP限流的内存管理
限流计数器存在内存里,如果不清理会一直涨。这次在每次限流检查时顺带清理过期的计数记录(超过1分钟的),这样不需要额外的定时任务,代码也更简洁。当然缺点是如果长时间没有请求,过期记录不会被主动清理,不过一个IP一条记录的内存占用可以忽略不计。
SqlAuditLog类型变更的连锁反应
改一个字段的类型看起来很简单,但userId在审计日志的调用链里传递了好几层:Controller→Aspect→AuditService→AuditLog。每一层的变量类型都要跟着改,漏一层就编译不过。这次逐层排查才确保全部改到位。
四、开发总结
这次完成了三批修复:
- Bug (多智能体循环迭代):AgentOrchestrator增加CriticAgent反馈循环,最多3轮迭代,SQL生成质量可自我修正
- Bug (前端XSS):escapeHtml函数补全5字符转义,排查5处innerHTML全部安全
- Bug (IP限流):AuthController登录注册接口增加基于IP的限流保护,1分钟5次上限
- Bug (类型一致性):SqlAuditLog.userId从String改为Long,同步修改AuditService和Aspect
- Bug (Repository暴露):代码审查确认无findAll()调用,风险已消除
本次开发提示词
修复Bug:在AgentOrchestrator中为多智能体协作增加循环迭代机制。CriticAgent审查SQL后如果发现问题,将反馈传递给generateSqlWithLLM重新生成,最多迭代3轮,通过后才执行。新增MAX_CRITIC_ITERATIONS常量和buildSqlCorrectionPrompt方法。 修复Bug:加强chat.js中escapeHtml函数的转义范围,从3个字符扩展到5个字符(增加双引号和单引号)。排查所有innerHTML使用位置,确保外部数据都经过转义。 修复Bug:为AuthController的登录和注册接口添加基于IP的限流保护,使用ConcurrentHashMap计数,1分钟窗口内同一IP最多5次请求,超限返回429。 修复Bug:将SqlAuditLog实体的userId字段从String改为Long,同步修改SqlAuditService的buildAuditLog方法和公开日志方法的参数类型,以及SqlSecurityAuditAspect中的userId变量类型。 修复Bug:排查QueryHistoryRepository的findAll()暴露风险,确认项目中无任何代码调用findAll()。