Skip to content

v0.2.0 — Security hardening + new tools

Choose a tag to compare

@ginkida ginkida released this 04 Jun 14:19
· 3 commits to main since this release

A security-hardening and capability release. No live exploit existed in 0.1.x, but the SQL whitelist relied entirely on the read-only connection; this release makes the validator independently sufficient, closes information-leak channels, fixes two correctness crashers, and adds two new tools.

🔒 Security (defense-in-depth)

  • Validator no longer depends on the read-only GUC alone — rejects data-modifying CTEs (WITH x AS (DELETE … RETURNING *) …), SELECT … INTO, and EXPLAIN ANALYZE over write statements.
  • Blocked dangerous function callspg_read_file, lo_*, dblink, set_config (exfiltration/escape vectors even under read-only).
  • Sensitive-column redaction (default on) — values of password/token/api_key/secret-like columns are replaced with <redacted> in query/sample/analyze. Metadata columns (token_count, password_changed_at, otp_enabled) are not affected. Disable with redact_sensitive = false.
  • Sanitized connection errors — host/user/dbname no longer leak to the agent; full detail goes to the server log only.
  • Resource boundsmax_profile_rows gate for analyze/anomalies, schema/FK/index caps, compare dedup + cap (with a visible note), config upper bounds, session statement_timeout + idle_in_transaction backstops.
  • Identifier regex uses \Z (trailing-newline safe); $1 is treated as a positional parameter, not a dollar-quote tag.

🐛 Correctness

  • Fixed numeric(20,2) overflow on large SUM/AVG in analyze/trend.
  • Per-column probes run inside savepoints — a failed probe is skipped (reported via skipped_columns) instead of aborting the whole profile; timeouts still propagate.
  • trend validates column types up front (clear errors instead of opaque failures).
  • Row counts are labeled as planner estimates (~N rows est.).

✨ New capabilities

  • describe — single-table schema + indexes (much cheaper than schema on large databases).
  • explain — query plan cost/row estimates without executing the query.
  • query gains offset paging and format="json".
  • Cells render NULL/bytes/JSON safely; display truncation is marked with an ellipsis.

🧰 Robustness / ops

  • main() validates config eagerly at startup and forces logging to stderr (stdout is the MCP channel).
  • ${ VAR } placeholders tolerate inner whitespace.

✅ Tests / CI

  • Test suite expanded 89 → 179 (read-only option, redaction, savepoint isolation, timeout budget, identifier-injection boundaries, new tools, full server tool layer).
  • CI pins ruff via dev extras and adds a build + wheel-import job.

Tools: 11 → 13 (added describe, explain). Backward-compatible; the one behavior change is redaction defaulting on.

Install: `pip install dbecho`