Pod

Available as Markdown and JSON. Pod is also available over MCP.

Reported issues for gaussdb-ro-mcp Desktop Extension

Pod holds 15 of 15 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to gaussdb-ro-mcp Desktop Extension.

Most discussed

tools: describe_table 各段错误处理不一致,constraints/indexes 失败被静默吞掉

问题描述

handleDescribeTable 对各段"尽力而为"查询的错误处理不一致:

影响

pg_constraint / pg_index 查询失败(权限被回收、ctx 取消)时工具返回"成功",constraints/indexes 键缺失——LLM 无法区分"无约束/索引"与"查询失败",会把表当成无主键分析下去,没有任何错误信号可供纠正。

位置

internal/tools/tools.go:150-175

建议修复

统一为 []struct{name string; fn func(...)}…

Read the thread · 2026-09-10 · closed · 1 comment

db: detectPartitionSupport 出错也消耗 sync.Once,分区检测被永久错判

问题描述

detectPartitionSupport 用 sync.Once 缓存探测结果,但出错也会消耗 Once:瞬时错误(ctx 取消、连接抖动——agent 重试场景下很常见)把 partitionMode 永久钉死为 false,无重试、无日志。

影响

进程余生中所有分区表被错标为 table(GaussDB parttype='p' 检测失效),describe_table 静默缺失分区清单,且无从发现。

位置

internal/db/meta.go:38-49

建议修复

仅缓存成功结果:出错时不清 Once 的完成位(例如把 Once 换成 atomic.Bool + "已确定"标志,或 Once 内部 err 非 nil 时重置可重入的状态)。

Read the thread · 2026-09-10 · closed · 1 comment

db: 亚毫秒 statement_timeout 截断为 0,反而禁用服务端超时

问题描述

enforceReadOnly 用 stmtTimeout.Milliseconds()(整数毫秒)格式化 SET statement_timeout。亚毫秒的配置时长(如 yaml statement_timeout: 100us,合法解析为 100µs 且 >0 通过 SetDefaults)被截断为 0——在 PG/GaussDB 中语义是禁用超时,与配置意图完全相反(已实证)。

位置

internal/db/manager.go:103

建议修复

向下取整后为 0 时钳制为最小 1ms(max(1, ms)),或在 config 层校验 statement_timeout 不得小于 1ms 并报配置错误。

Read the thread · 2026-09-10 · closed · 1 comment

config: 未知 YAML 键被静默忽略,拼错的限制项实际在用默认值

问题描述

Load 使用不带 KnownFields 的 yaml.Unmarshal,未知/拼写错误的 YAML 键被静默忽略。

影响

server:
  max_row: 5000      # max_rows 拼错
  stmt_timeout: 10s  # 拼错

加载零错误零日志,服务器以 max_rows=500、statement_timeout=30s 运行。运维以为设了紧约束,实际每个查询都在用默认语义——对一个以"限制"为核心卖点的工具尤其危险。

位置

internal/config/config.go:240

建议修复

改用 yaml.Decoder + dec.KnownFields(true) 拒绝未知键(注意 Duration 自定义 Unmarshal 兼容性);若担心破坏既有配置,至少对常见拼写在加载日志中告警。

Read the thread · 2026-09-10 · closed · 1 comment

config: blocked_functions 文档称前缀匹配、实现为精确匹配;非空配置会整体替换默认黑名单

问题描述

blocked_functions 的文档与实现不符,且替换语义未声明:

  1. config.go:46 注释与 gaussdb-ro-mcp.example.yaml 称"前缀匹配",但 isBlockedFunction 只对以 * 结尾的条目做前缀匹配,其余是剥通配后的精确匹配。按文档写 pg_advisory 期望前缀覆盖,实际只有精确名 pg_advisory 被拦,pg_try_advisory_lock 等全部通过第 1 层。
  2. schema 限定条目(如 pg_catalog.dblink)永远不匹配——比对只取尾段。
  3. 配置任何非空 blocked_functions 会整体替换默认黑名单(dblink*、set_config、pg_read_file*…),追加一个 pg_sleep 会把其余全部放行,且无任何提示。

位置…

Read the thread · 2026-09-10 · closed · 1 comment

config: BuildDSN 不转义密码(含空格即损坏);ensureSSLMode 子串匹配可被密码抑制

问题描述

两个字面量拼接缺陷:

  1. BuildDSN 发出不加引号的 keyword=value 对。密码含空格(或引入歧义的字符)时产生损坏的 DSN:pass word@2026 → password=pass word@2026 sslmode=disable,驱动解析器在空格处截断值、把 word@2026 当非法关键字 → "初始化实例失败"或密码错误(已实证)。
  2. ensureSSLMode 用子串 Contains("sslmode=") 判断整个 DSN:密码中恰好含 sslmode=(如 xK3sslmode=9q)时,DSN 路径上预期的默认 sslmode 被抑制,驱动静默回退 prefer。

位置

internal/config/config.go:163-180(BuildDSN)、config.go:207-224(ensureSSLMode)

建议修复

Read the thread · 2026-09-10 · closed · 1 comment

tools: test_connection 在 transaction_read_only=off 时仍报 ok:true

问题描述

test_connection 在 SHOW transaction_read_only 查询成功时即报 "ok": true,即使查询返回的是 off。一个以"只读状态检查"为卖点的工具,对恰好是 enforceReadOnly 要抓的故障形态(启动参数被代理剥离、会话可写)亮绿灯。

复现

对启动参数被剥离、会话实际可写的池调用 test_connection:

{"ok": true, "transaction_read_only": "off"}

位置

internal/tools/tools.go:92("ok": roErr == nil)

建议修复

ok 应要求 strings.EqualFold(ro, "on"),与 enforceReadOnly 的判定一致;off 时可附 read_only_check_error: "transaction_read_only=off" 之类的显式错误信息。

Read the thread · 2026-09-10 · closed · 1 comment

db: Select/Query 行 map 按列名建键,重复列名静默丢数据

问题描述

Instance.Select(及 Query)的行映射以输出列名为 map 键:重复列名时第 N 列的值静默覆盖第 1 列的值,Columns(长度 N)与行 map(键更少)不一致。

复现

SELECT u.id, o.id FROM users u JOIN orders o ON u.id = o.user_id

返回 columns: ["id","id"],但每行 map 只剩一个 id 键(持有第二个 id)——第一列数据静默丢失,且 truncated: false、row_count 正常,消费结果的 agent 无法察觉丢失。

位置

internal/db/manager.go:204-215(Select 行循环)、manager.go:236-248(Query 同样问题)

建议修复

任选其一:

  1. 行结构改为 []any 按位置对应 columns(破坏现有 map 形态,需评估客户端兼容);
  2. 保留 map…

Read the thread · 2026-09-10 · closed · 1 comment

Most recent

db: newInstance 无条件覆盖 ConnectTimeout,实例级 connect_timeout 配置失效

问题描述

newInstance 在 gaussdbxpool.ParseConfig 之后无条件用服务级值覆盖 poolCfg.ConnConfig.ConnectTimeout,静默丢弃用户通过 DSN 或 options 传入的实例级 connect_timeout——而 config.go:65 的注释明确把 connect_timeout=5 列为受支持的 Options 条目(驱动确实会解析它,见 vendored gaussdbconn/config.go:281-287)。

影响

instances:
  - name: slow-endpoint
    options: ["connect_timeout=1"]   # 期望 1s
# server.connect_timeout 未设置 → 默认 10s

连接黑洞时尝试会停滞约 10s 而非配置的 1s,且无任何提示。

位置

internal/db/manager.go:74

建议修复

仅当实例/DSN…

Read the thread · 2026-09-10 · closed · 1 comment

config: instances 列表含空项时 SetDefaults 解引用 nil 而 panic

问题描述

YAML 中 instances: 列表的空列表项解码为 nil *Instance 指针,而 Load 的调用顺序是先 SetDefaults() 再 validate()——SetDefaults 在 inst.SSLMode == ""(config.go:110)处对 nil 解引用,直接 panic。

复现(已实证)

instances:
  -
  - name: ok

config.Load 以 runtime error: invalid memory address or nil pointer dereference panic(stderr 带堆栈),而不是走文档化的"配置加载失败"错误路径。

位置

internal/config/config.go:108-124(SetDefaults 的实例循环)与 config.go:241-245(Load 中 SetDefaults 先于 validate)

建议修复

任选其一: 1.…

Read the thread · 2026-09-10 · closed · 1 comment

main: SIGINT/SIGTERM 优雅退出被当作崩溃(退出码 1)

问题描述

SIGINT/SIGTERM 触发 signal.NotifyContext 取消后,MCP SDK 的 Server.Run 返回 ctx.Err()(context.Canceled,见 vendor 内 mcp/server.go:1295-1303)。而 main 中 start 返回的任何非空错误都走 logger.Fatalf → os.Exit(1)。

结果:每次正常关闭都被记录为崩溃——日志打出 gaussdb-ro-mcp 退出: context canceled,退出码 1。与第 55 行"优雅退出"注释矛盾;systemd Restart=on-failure 会重启循环,MCP 客户端会把服务器记为异常退出。

复现

启动 stdio 服务器 → 发送 SIGTERM(或客户端关闭 agent 时的常规信号)→ 观察退出码 1 与 fatal 日志。

位置

cmd/gaussdb-ro-mcp/main.go:70(start 返回 server.Run…

Read the thread · 2026-09-10 · closed · 1 comment

[安全] db: enforceReadOnly 中 SET statement_timeout 先于 ROLLBACK,破坏只读回退路径且可致连接无超时入池

问题描述

enforceReadOnly 的执行顺序是:先 SET statement_timeout,再回读校验只读,失败才 ROLLBACK + 会话级 SET READ ONLY 回退。这个顺序破坏了注释(manager.go:113-118)所描述的恢复路径:

位置

internal/db/manager.go:101-129(第 103 行 SET 与第 117 行 ROLLBACK 的顺序)

建议修复

调整顺序:回读校验失败 → 先…

Read the thread · 2026-09-10 · closed · 1 comment

[安全] guard: 咨询锁黑名单枚举了不存在的函数名,遗漏 pg_try_advisory_* 系列(可致持久 DoS)

问题描述

defaultBlockedFunctions 中咨询锁一节枚举了三个不存在的函数名:

同时遗漏了真实的:

而 README 和 gaussdb-ro-mcp.example.yaml 均声称 pg_advisory_* 默认被拦截。

影响

咨询锁在只读事务中是允许的,第 2 层会话只读无法兜底:

SELECT…

[Read the thread](https://github.com/gxc/gaussdb-ro-mcp/issues/3) · 2026-09-10 · closed · 1 comment

### [安全] guard: 引号标识符函数名("dblink"(...) 等)完全绕过危险函数黑名单

## 问题描述

`tokenize` 给引号标识符 token 加了 `\x00` 前缀(`guard.go:241`),使其不参与关键字匹配;但危险函数黑名单检查以 `isWordToken(t)` 为门槛(`guard.go:86`),而 `isWordToken` 拒绝以 `\x00` 开头的 token——于是**用引号包裹函数名即可完全绕过黑名单**:

```sql
SELECT "dblink"('host=10.0.0.1 dbname=x', 'insert into t values(1)')   -- 通过
SELECT "set_config"('statement_timeout','0',false)                     -- 通过
SELECT pg_catalog."pg_read_file"('postgresql.conf',0,100)              -- 通过
SELECT "nextval"('s')                                                  -- 通过…

[Read the thread](https://github.com/gxc/gaussdb-ro-mcp/issues/2) · 2026-09-10 · closed · 1 comment

### [安全] guard: E''/U&'' 反斜杠判定忽略邻接关系,字符串边界反转可隐藏 set_config/dblink 调用

## 问题描述

`internal/guard/guard.go` 的 `tokenize` 在处理字符串字面量时,通过检查**前一个 token 是否为 `e`/`u`** 来决定是否启用反斜杠转义(E''/U&'' 语法),但忽略了邻接关系:即使 `e`/`u` 只是一个普通的列名/别名 token(与后面的字符串之间隔着逗号等标点),也会让后续字符串按转义语法 lex。

这会**反转 guard 与服务端之间的字符串边界认定**:

- **绕过方向**:guard 认为 `'\'` 是转义字符串的一部分,把紧随其后的 `set_config(...)`、`dblink(...)` 等吞进字符串;而服务端(`standard_conforming_strings=on`)认为 `'\'` 是完整字符串,危险函数真实执行。
- **误拒方向**:合法 SQL `SELECT e, '\' FROM t`(`e` 是列名)被误报"SQL 存在未闭合的字符串字面量"。

## 复现(已实证)

```sql
SELECT e, '\',…

[Read the thread](https://github.com/gxc/gaussdb-ro-mcp/issues/1) · 2026-09-10 · closed · 1 comment

The remaining reports are on [the project's issue tracker](https://github.com/gxc/gaussdb-ro-mcp/issues).