mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 00:31:58 +00:00
26ff8e1e06
守卫只看首关键字,而 with / pragma 都在只读白名单里。在只读的 SQLite 源上 实测:`WITH k AS (SELECT 1) DELETE FROM t` 被放行,5 行删得只剩 2 行; `PRAGMA user_version = 7` 也写进去了。调用方只看到一个 ResourceClosedError—— pysqlite 只在 INSERT/UPDATE/DELETE 开头的语句前隐式开事务,WITH 开头的直接 自动提交,连接关闭时的回滚兜不住。Excel/CSV 上传生成的正是这种 SQLite 源。 两层一起收: 守卫:以查询开头的语句(SELECT / WITH / EXPLAIN)要把正文扫一遍,先抹掉注释 和引号里的内容,再找写关键字(DELETE、UPDATE、INTO、FOR UPDATE、EXPLAIN ANALYZE 里的语句……),关键字后紧跟 ( 的是同名函数不算(MySQL 的 INSERT()、 TRUNCATE())。PRAGMA 改成只读白名单,`= 值` 和 `(值)` 两种赋值写法都拦。 另收一小撮有副作用的函数,其中 set_config 必须拦:PG 真库实测,它能把连接层 的只读关掉,同一连接的下一个事务就能写。函数名加引号、dblink 另开连接这两种 绕法也补上了。is_write 与只读判定共用一份判定,免得审批那道门另有一套口径。 连接层:只读源连接时就只读(engine_args)。SQLite 以 mode=ro 打开(file: URI, 路径带空格、中文、# 都测过);PostgreSQL 设会话默认事务只读;MySQL / MariaDB 设会话事务只读。Oracle 没有会话级开关,只剩守卫——README 写明请配只读账号。 真库验证(临时实例,已清理):PostgreSQL 18 与 MySQL 8.0 上,DELETE、WITH … DELETE、 PG 的数据修改 CTE、nextval、EXPLAIN ANALYZE 绕过守卫直连执行,都被数据库以 只读事务拒绝;可写源不受影响。 测试:守卫新增 33 例(藏在查询里的写、会写的 PRAGMA、同名函数与引号标识符不误杀), 去掉修复重跑是 17 例失败;test_readonly_source.py 6 例(当初那条绕过、绕过守卫 直连写、中文路径、可写源不受波及、各库的会话参数)。297 → 334 passed。 顺带查到但没在这里修的:可写源上的写操作既不审批也不生效——is_dangerous_call 全仓库没人调用,而 run_query 从不 commit,写完就被回滚。两件事必须一起修 (先接审批再让写入生效,反过来就是一个无审批写库的窗口),放在审批统一那一步。