一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

SQLGuard MCP 如何在 AI 与数据库之间拦截危险 SQL?

时间:2026-09-13 11:22:01 编辑:袖梨 来源:一聚教程网

SQLGuard MCP 的定位不是替代数据库权限,而是在 AI 客户端与 PostgreSQL 或 SQLite 之间增加一道查询防火墙。根据项目作者发布时的说明,它会先分析模型提交的 SQL,把语句分成读取、写入和破坏性操作,再按运行模式决定直接放行、返回预执行摘要、要求确认或拒绝。这个设计解决的核心问题是:模型能够生成语法正确的 SQL,却不一定理解生产数据的边界,也可能因为提示注入、上下文误解或工具调用错误而执行高风险语句。

需要先说明核验边界:原始介绍帖给出了架构、模式和启动参数,但其指向的公开代码仓库在本文核验时返回不存在。因此,下面关于 SQLGuard MCP 自身实现的描述以作者公开说明为依据,不能等同于已经审计源码后的安全结论。准备采用它的团队应先确认可获取的包、源码、版本和维护者身份;如果这些材料无法复核,不应把它直接接入生产数据库。

查询防火墙位于哪里

常规数据库 MCP Server 接收模型生成的工具参数,建立数据库连接并执行 SQL。SQLGuard MCP 插在客户端与数据库之间,让所有查询先经过分类与策略判断。只有策略允许的语句才会到达数据库驱动。

这个位置很重要。系统提示词只能告诉模型不要删除数据,却不能保证模型始终遵守;数据库权限可以在最终层阻止越权,却很难为用户解释某条语句为何危险。中间防火墙可以在执行前给出结构化判定,为审批、审计和开发调试提供可见依据。

防火墙仍不是唯一入口。如果应用、运维脚本或其他 MCP Server 可以绕过它直连数据库,同一策略就不会覆盖这些流量。部署时要画清连接路径,确认 AI 客户端只能拿到防火墙端点,真实数据库凭据不暴露给模型侧进程。

第一阶段使用 AST 解析

作者说明第一阶段使用 node-sql-parser 把标准 SQL、CTE、子查询和 JOIN 转换为抽象语法树。AST 判断关注的是语句结构,而不是文本里是否出现某个单词。

例如,字符串值可能包含 delete,表名可能包含 update,注释里也可能出现 drop。简键词扫描会把这些合法读取误判成写操作。相反,多语句批次、嵌套表达式或经过换行与注释变形的危险语句又可能绕过脆弱正则。解析器能识别顶层语句类型、目标对象和子节点,判定基础通常更可靠。

AST 也并非天然完整。不同数据库方言拥有专有函数、操作符、DDL 和过程调用语法。解析器版本不认识的新语法可能解析失败,也可能形成意料之外的节点。安全实现必须对未知节点采取明确策略,不能因为无法识别就默认允许。

第二阶段为什么仍使用正则

原帖称第二阶段会在解析器遇到动态 SQL 或非标准语法时使用正则回退。这个安排提高了兼容性,但也是最需要谨慎评估的部分。

回退规则适合识别清晰的危险标记,例如明显的 DDL 动词或某些方言特有结构。它不适合证明一段任意 SQL 是安全的,因为注释、引号、转义、编码和动态拼接都可能改变文本与执行语义之间的关系。

安全的回退原则应该是失败关闭:解析失败且规则不能明确证明语句属于允许集合时,拒绝执行并返回原因。不能把“正则没有匹配到危险词”等同于“查询安全”。原帖明确声称服务在崩溃或离线时会失败关闭,但实际部署仍需通过断进程、制造解析错误和断开依赖进行验证。

READ、WRITE 与 DESTRUCTIVE 分类

READ 类通常包括 SELECT,以及以读取为最终语句的 CTE。它们不修改持久数据,但并不代表无风险:全表扫描会消耗资源,敏感列会泄露信息,数据库函数可能带有副作用,查询结果还可能携带提示注入文本。

WRITE 类通常包括 INSERT、UPDATE、DELETE 等数据修改。它们可能是正常业务操作,却需要确认影响范围、过滤条件、事务边界和回滚方案。没有 WHERE 的 UPDATE 与只更新一行的参数化语句显然不应拥有相同风险等级。

DESTRUCTIVE 类通常包括 DROP、TRUNCATE、危险 ALTER,以及会大范围破坏结构或数据的操作。生产环境应默认阻断,而不是只弹出一个容易被模型自动确认的提示。

三分类便于理解,但真实风险不是离散的。SELECT FOR UPDATE 会锁行,CREATE TEMP TABLE 会写临时结构,存储过程可能执行任意副作用,数据库扩展函数甚至可能访问文件或网络。上线前必须用目标数据库的完整语法清单补充分类测试。

read-only 模式

read-only 模式只允许被判定为读取的查询,写入和破坏性操作都拒绝。它适合数据分析、模式探索、报表问答和生产故障只读诊断。

模式名称不能替代只读数据库账户。如果防火墙分类存在漏洞,而连接账户拥有写权限,漏过的一条语句仍可造成真实修改。正确做法是给该模式配置数据库原生只读角色,并限制到批准的库、模式、表、视图和列。

还要限制查询成本。设置语句超时、返回行数、并发、内存和连接数上限;复杂读取同样可能拖慢生产实例。对于敏感数据,优先暴露脱敏视图,不直接开放基础表。

strict 模式

strict 模式下,读取可直接通过;写入先返回 dry-run 摘要并等待确认;破坏性操作阻断。这是交互式开发场景中最有价值的模式,因为它既允许模型协助修改数据,又在真正执行前插入人工判断。

dry-run 摘要至少应包含规范化语句、目标数据库与表、操作类型、是否有过滤条件、参数值的脱敏表示、预计影响行数以及事务信息。只显示“将执行写操作”不足以帮助审批者判断风险。

确认必须绑定到原始查询的不可变摘要或哈希,并设置短时有效期。否则模型可能先提交一条低风险语句获得确认,再替换参数或 SQL 内容执行另一条语句,这属于检查与使用之间的竞态。

审批动作应由真实用户触发,不能把确认工具自动暴露给同一个模型。若模型既能申请又能批准,strict 模式只增加一次工具调用,并未形成独立控制。

permissive 模式

permissive 模式允许所有语句执行,并对破坏性操作记录日志。它适合本地临时数据库、一次性测试容器或专门的演示环境,不适合作为共享或生产数据库的默认配置。

日志发生在操作之后,无法恢复被删除的数据。即使存在备份,恢复时间、日志窗口和外部副作用也可能造成业务损失。因此 permissive 的安全边界应来自环境隔离、短期凭据和可丢弃数据,而不是审计记录。

测试环境也要防止误连生产。连接字符串应由环境注入,数据库名与主机名显示在工具响应中,并对生产主机设置网络策略。不要依赖开发者肉眼识别一长串连接地址。

最小启动配置如何理解

作者给出的示例通过 npx 启动,并用 DATABASE_URL 指定连接,用 SQLGUARD_MODE=strict 选择严格模式。这个示例说明了配置入口,但不意味着可以直接复制到生产。

DATABASE_URL='postgresql://guard_user:[email protected]/appdb'
SQLGUARD_MODE='strict'
npx sqlguard-mcp

凭据不要写进可提交的客户端配置。优先使用秘密管理、受限环境变量或本地凭据代理。固定包版本与完整性摘要,避免每次启动解析到不同的最新版本。

由于公开仓库当前无法核验,运行任何包之前还应检查软件包发布者、源码链接、依赖树、安装脚本和签名。包名可被抢注或仿冒,单凭帖子中的命令不足以建立供应链信任。

PostgreSQL 最小权限

为防火墙创建独立登录角色,不授予超级用户、建库、建角色或复制权限。按模式决定是否拥有写权限,并把授权收窄到指定 schema 和对象。

CREATE ROLE sqlguard_reader LOGIN PASSWORD 'replace-me';
GRANT CONNECT ON DATABASE appdb TO sqlguard_reader;
GRANT USAGE ON SCHEMA reporting TO sqlguard_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA reporting TO sqlguard_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA reporting
GRANT SELECT ON TABLES TO sqlguard_reader;

如果 strict 模式需要写入,单独建立 writer 角色,仅授予批准表的 INSERT 或 UPDATE,不授予表所有权。通过视图、行级安全策略和列权限进一步限制可见与可改范围。

还要控制函数执行权限。PostgreSQL 函数可能是 VOLATILE,也可能以定义者权限运行。只判断 SELECT 会漏掉 SELECT dangerous_function() 这类副作用入口。

SQLite 的权限边界不同

SQLite 没有服务器端角色体系,权限主要来自数据库文件和目录的操作系统权限。只读模式应以只读 URI 打开文件,并确保进程无法写入数据库所在目录。

仅把数据库文件设为只读仍可能遇到 journal、WAL、临时文件和旁路文件访问问题。为只读分析准备副本或快照通常更可靠,敏感主库不应直接挂载给可执行任意查询的 Agent。

SQLite 扩展加载也应关闭。若运行时允许加载本地扩展,查询能力可能扩展为本机代码执行,远远超出 SQL 分类器的模型。

失败关闭需要怎样验证

失败关闭的含义是:分类器异常、策略文件不可读、依赖崩溃或网络状态不确定时,查询不能绕过检查直接到达数据库。返回错误比猜测安全更合适。

测试时可以让解析器接收无效语法、模拟分类器抛异常、删除策略配置、在请求中途终止进程,并检查数据库审计日志是否出现对应语句。还要验证重启后不会把未决确认自动视为已批准。

系统可用性与安全性需要分别设计。失败关闭可能让数据库助手暂时不可用,因此应提供健康检查、告警和人工直连的受控应急流程,而不是在故障时切换为无检查直通。

多语句与注释绕过测试

测试集应包含分号连接的多条语句、前后注释、块注释、大小写混合、Unicode 空白、字符串中的关键词和嵌套 CTE。分类结果必须对应可执行结构,而不是第一段文本。

SELECT id FROM users WHERE id = 7;
DROP TABLE users;

如果产品只允许单条语句,应在 AST 层确认整个输入只有一个可执行 statement。驱动是否默认支持多语句也要单独确认,不能依赖解析器与驱动恰好行为一致。

为每个曾经修复的绕过样例增加回归测试,并固定解析器版本。依赖升级可能改变 AST 形状,导致原有策略漏判或误判。

动态 SQL 与存储过程

动态 SQL 是正则回退最危险的边界之一。字符串拼接出的语句只有在数据库运行时才获得完整含义,外层可能只是 EXECUTE、PREPARE 或函数调用。

保守策略是阻止所有动态执行和任意存储过程,只为经过审查的过程建立名称与参数白名单。白名单不能只检查过程名,还要限制参数类型、长度和业务范围。

若业务确实需要动态查询,最好把能力封装成服务器端固定接口,让模型传结构化过滤条件,而不是传任意 SQL 文本。这样权限、参数化和审计都更可控。

确认机制的事务语义

dry-run 与真实执行之间,数据可能已经变化。先运行 SELECT COUNT 估计影响行数,再执行 UPDATE,并不能保证两次看到相同集合。

需要强一致审批时,可在事务内锁定目标集合,或让审批摘要绑定主键集合和版本条件。但锁等待会影响线上业务,主键集合也可能很大,必须根据场景权衡。

更常见的做法是强制写语句带主键或窄范围条件,设置最大影响行数,在执行后核对实际行数,超限立即回滚。数据库事务是最后防线,防火墙摘要只是决策辅助。

审计日志应该记录什么

审计至少记录时间、请求主体、客户端会话、数据库目标、分类结果、策略模式、查询摘要、审批者、执行结果、影响行数和关联追踪标识。原始 SQL 是否完整保存取决于数据敏感度。

参数可能包含密码、令牌、个人信息和商业数据。日志应脱敏、限制访问并设置保留周期。审计存储要与运行服务隔离,避免拥有数据库查询能力的同一进程修改历史记录。

不要只记录 destructive。被允许的读取也可能构成数据外泄,连续的小范围 SELECT 也可能拼出完整敏感数据。审计策略要与数据分类和用户身份结合。

提示注入仍然存在

查询防火墙分析 SQL,不分析返回行里的自然语言。数据库中的工单、评论或网页抓取内容可能包含诱导模型泄露信息、调用其他工具或忽略规则的文字。

所有数据库结果都应标记为不可信数据。结果不能修改系统提示、工具授权或审批状态。把查询工具与发消息、执行命令、访问秘密等高风险工具隔离,避免一次数据注入形成跨工具攻击链。

限制返回列和行数也有帮助,但不能从根本上消除注入。真正的边界是 Agent 编排层对数据与指令的区分,以及每个工具独立的权限控制。

坚控误判与漏判

误判会阻断合法工作,漏判会放行危险操作。上线初期可在隔离环境运行影子分类,把判定结果与人工标注对比,再决定是否进入强制模式。

指标应包括各类别数量、拒绝率、解析失败率、正则回退率、确认通过率、策略延迟和数据库错误率。正则回退比例突然升高,可能表示出现新方言、新版本语法或主动绕过尝试。

不要为了降低误判率而把未知语法默认放行。先补充解析支持和测试,再扩大允许集合。安全规则的变化应经过代码审查并可回滚。

一套可执行的验收清单

第一,确认代码、包和维护者身份可复核,固定版本并检查依赖与安装脚本。当前公开仓库不可访问时,暂停生产采用,直到获得可信源码或可审计制品。

第二,在 PostgreSQL 和 SQLite 分别建立隔离测试库,准备读取、写入、DDL、多语句、动态 SQL、存储过程、方言扩展和资源消耗样例,验证分类与真实执行结果一致。

第三,验证 read-only、strict、permissive 三种模式的每个决策分支,尤其检查 destructive 是否在 strict 中不可被模型自行确认,以及未知语法是否失败关闭。

第四,使用数据库原生最小权限、超时、行数、并发、网络与文件系统隔离。故意绕过防火墙直连数据库,确认客户端没有真实凭据和替代路径。

第五,检查确认绑定、事务竞态、审计脱敏、告警与恢复流程。破坏分类器进程和配置,确认故障不会退化为直通。

SQLGuard MCP 展示了一个合理的安全结构:AST 负责理解常规语句,回退规则处理解析边界,策略模式决定执行路径,失败关闭防止检查器故障时静默放行。真正可靠的部署还需要可审计源码、数据库最小权限、不可伪造的人工确认、方言回归测试和完整审计。它应当是一层纵深防御,而不是给任意数据库凭据加上一个“安全”标签。

热门栏目