PostgreSQL Field Guide

安全 SQL 护栏

只读优先、最小权限、超时、行数限制与写操作审批

数据库角色是第一道边界

CREATE ROLE agent_reader LOGIN;
GRANT CONNECT ON DATABASE commerce TO agent_reader;
GRANT USAGE ON SCHEMA app TO agent_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA app TO agent_reader;
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA app
  GRANT SELECT ON TABLES TO agent_reader;

ALTER ROLE agent_reader SET default_transaction_read_only = on;
ALTER ROLE agent_reader SET statement_timeout = '5s';
ALTER ROLE agent_reader SET lock_timeout = '1s';
ALTER ROLE agent_reader SET idle_in_transaction_session_timeout = '10s';

凭据由 secret manager 或云身份集成配置,不要保存在迁移文件、prompt 或工具响应中。确认该角色不能 SET ROLE 到更高权限角色。

执行前策略

对模型生成的 SQL 做 parser/AST 级校验,不用正则代替解析器。默认规则:

  • 只允许单条 SELECT
  • 拒绝 COPY ... PROGRAM、大对象、外部数据包装器和危险函数。
  • 拒绝多个语句和注释绕过。
  • 限制可访问 schema、表和列。
  • 强制参数绑定;标识符只能从白名单选择。
  • 对非聚合结果施加 LIMIT,同时在驱动层设置最大返回字节数。
  • 执行 EXPLAIN (FORMAT JSON) 做成本预检时,不能把成本估算当作时间保证。

每次读取使用只读事务

BEGIN READ ONLY;
SET LOCAL statement_timeout = '5s';
SET LOCAL lock_timeout = '1s';
SET LOCAL search_path = app, pg_catalog;

SELECT id, status, total_cents
FROM orders
WHERE customer_id = $1
ORDER BY placed_at DESC
LIMIT 100;

COMMIT;

只读事务仍可能运行昂贵查询并泄露可读取的数据,所以权限、成本和结果限制缺一不可。

写操作不要开放任意 SQL

优先向 Agent 暴露领域工具:

{
  "tool": "cancel_order",
  "arguments": {
    "order_id": 8842,
    "expected_status": "pending",
    "reason": "duplicate order",
    "idempotency_key": "case-2026-184"
  }
}

应用服务验证身份与状态转换,在事务中执行参数化 SQL,并返回明确结果。批量写、DDL、GRANT、备份恢复和复制配置不应暴露给通用 Agent。

审计字段

至少记录:请求者/租户、工具名、模型与提示版本、契约版本、数据库目标、SQL 指纹(参数脱敏)、风险级别、审批者、行数、耗时、SQLSTATE、是否截断。不要把原始敏感结果复制进普通日志。

行数检查不能替代事务设计

先执行写入再发现“影响太多行”可能已经触发触发器或产生外部事件。应在受控事务里预览目标集,或通过领域 API 将可修改集合限制在查询本身。

Last updated on

On this page