先把结论甩前面:让智能体把人话翻成SQL去查库,最该防的不是它写不对查询,是它在你没盯着的时候,把一句"帮我清理下过期数据"执行成了真的DELETE。下面这几个坑,我都是踩过血才知道要拦在哪一层。

起因是上个月,运营那帮人天天来找我跑数。"看看上周华东区退款单多少""把昨天注册没下单的用户拉给我"——一天七八次,我SQL写到手软。后来我花了俩晚上,拿一个零代码就能配智能体的工具,搭了个"查数小助手":挂个大模型,把库表结构喂进去当知识,运营直接打字问,它生成SQL、跑、把结果用大白话回出来。第一版上线那天我挺得意的。然后第三天,差点出事。

坑1:它真的会写出 DELETE / DROP

我以为模型只会SELECT。天真。有个运营手抖打了句"删掉这些测试订单",小助手就老老实实生成了DELETE FROM orders WHERE ...,还准备执行。幸好我连的是只读账号,它报权限错了才被我发现。

解法,按优先级排:

  1. 数据库层给只读账号。这是底线,别的全失效时它还在。建个只有SELECT权限的account,智能体只能用这个连。GRANT SELECT ON db.* TO 'agent_ro'@'%';——就这一句,挡掉八成事故。

  2. SQL执行前做语句类型白名单。解析出来不是SELECT开头的,直接拒,连库都不连。

别嫌两层重复,数据库权限是兜底,白名单是早拦,两个都要。

坑2:运营的话里能藏注入

这个更阴。有人问:"查一下用户名等于 a' OR '1'='1 的记录"。模型很听话,把那串原样拼进了SQL。虽然是查询,但条件被撑开了,返回了全表。

防法只有一个真管用的:别让模型直接生成带值的完整SQL。让它生成带占位符的模板 + 一组参数,你这边用参数化查询(prepared statement)去填。WHERE name = ?,值单独走绑定。模型负责结构,值永远不进SQL字符串。我后来还顺手加了条:生成的SQL里要是出现明文常量值而不是占位符,打回重生成。

坑3:一句"全量"能把库拖垮

SELECT * FROM orders,八百万行,没LIMIT。智能体不懂什么叫慢查询,运营也不懂,库懂——直接卡给你看。

  • 强制给生成的SQL尾部塞LIMIT 1000(没有就补上);

  • 给这个只读账号单独设查询超时,MySQL里max_execution_time几秒就够,跑超了自己断;

  • 复杂JOIN我干脆加了层校验,扫到三张表以上的关联先人工过一眼。

坑4:表结构全喂进去 = 把家底亮给模型

为了让它生成准,我一开始把整库schema全塞知识库了,包括user_password_hashid_card那些字段。后来反应过来,模型生成时完全可能把敏感列写进SELECT只喂业务真用得上的表和字段,敏感列在那层零代码工具里直接不进知识库,它看不见就查不到。

一点不吹的实话

搭这玩意儿没编程,拖拖配配两小时,但调prompt和这几道防护卡,我前后弄了快两天,中间还跑题去研究了半天怎么让它把结果排成表格——后来发现纯属多余,运营要的是数,不是好看。它也就只能干"查数"这种杂活,真复杂的分析还得我自己上。响应也不算快,一句问下去得等个三五秒。

但说真的,运营现在不找我了,这点就值。

防注入防删库这事,核心就一句:别信模型的输出,信你卡的那几道关。只读账号、参数化、LIMIT、敏感列不外露,四道叠上,出事概率低到能睡着觉。

你们让Agent查库踩过啥更野的坑?评论区聊聊,我想看看还有哪个角度我没堵上。

(模型这块我直接调的讯飞星辰MaaS,现成大模型API,没自己搭算力,省了部署那摊事)

Logo

一站式 AI 云服务平台

更多推荐