Reported issues for postgres-scout-mcp
Pod holds 16 of 17 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.
Back to postgres-scout-mcp.
Most discussed
Make file logging opt-in instead of default
Problem
The Logger in postgres-scout-mcp always creates a ./logs directory and writes log files to disk by default. In contrast, mongo-scout-mcp uses an ENABLE_LOGGING environment variable that defaults to false, making file logging opt-in.
Expected Behavior
File logging should be opt-in via ENABLE_LOGGING=true environment variable, matching the pattern used in mongo-scout-mcp.
Current Behavior
- Logger constructor unconditionally creates the log directory
- Every
log()c
Read the thread · 2026-03-07 · closed · 0 comments
DDL operations unrestricted in read-write mode
Summary
Read-write mode allows all DDL operations (CREATE, ALTER, DROP, TRUNCATE) via executeQuery with no additional confirmation or restriction.
Affected Files
src/utils/sanitize.ts—ALLOWED_READ_WRITE_OPERATIONS(lines 4-9)
Problem
Read-write mode is intended for safe data modifications (INSERT, UPDATE, DELETE with guards). However, it also allows destructive DDL like DROP TABLE, TRUNCATE, and ALTER TABLE through the general executeQuery tool, without the safety
Read the thread · 2026-02-28 · closed · 0 comments
Log injection via unsanitized tool arguments
Summary
Tool names and arguments are logged without sanitization, allowing control characters and newlines to pollute or forge log entries.
Affected Files
src/server/setup.ts— line 51:logger.info('mcp', \Tool called: ${name}`, { args })`src/utils/logger.ts
Problem
If tool arguments contain newlines or control characters, they are written directly to log files. This could be used to forge log entries or mask malicious activity in the audit trail.
Suggested Fix
St
Read the thread · 2026-02-28 · closed · 0 comments
No server-side cap on maxRows for mutation tools
Summary
The maxRows parameter in safeUpdate and safeDelete is fully controlled by the MCP client with no server-side upper bound.
Affected Files
src/tools/mutations.ts—SafeUpdateSchema(line 28),SafeDeleteSchema(line 38)
Problem
The maxRows parameter defaults to 1000 but can be set to any number by the agent. There is no server-enforced maximum. An agent can pass maxRows: 999999999 to effectively disable the safety guard.
Suggested Fix
Add a server-side m
Read the thread · 2026-02-28 · closed · 0 comments
Rate limiting disabled by default
Summary
Rate limiting is disabled by default, providing no protection against rapid-fire tool calls.
Affected Files
src/config/environment.ts— line 42:enableRateLimit: process.env.ENABLE_RATE_LIMIT === 'true'
Problem
The rate limiter exists but defaults to off. Without rate limiting, there is no throttling of tool invocations, making it easier to abuse expensive operations or amplify other vulnerabilities.
Suggested Fix
Enable rate limiting by default. Users who need h
Read the thread · 2026-02-28 · closed · 0 comments
Information disclosure via unfiltered error messages
Summary
PostgreSQL error messages are returned directly to the MCP client without sanitization, potentially leaking internal schema details.
Affected Files
src/server/setup.ts— error handler (lines 66-82)src/utils/database.ts— query error logging (lines 85-92)
Problem
When queries fail, the raw PostgreSQL error message is forwarded to the client. These messages often contain table names, column types, constraint names, query fragments, and internal database state that ca
Read the thread · 2026-02-28 · closed · 0 comments
Connection pool exhaustion via parallel queries in findDuplicates
Summary
findDuplicates with includeRows=true (the default) fires unbounded parallel queries that can exhaust the connection pool.
Affected Files
src/tools/data-quality.ts—findDuplicates()(lines 94-119)
Problem
When includeRows=true, the tool uses Promise.all() to fire a query for each duplicate group simultaneously. With the default limit=100, up to 100 concurrent queries are fired against a pool that defaults to 10 connections. This blocks all other database ope
Read the thread · 2026-02-28 · closed · 0 comments
Always-true WHERE clause bypass in mutation protection
Summary
The normalizeWhereForSafety() function in mutation tools can be tricked into failing to detect always-true WHERE clauses, bypassing the allowEmptyWhere protection.
Affected Files
src/tools/mutations.ts—normalizeWhereForSafety()(lines 41-49),validateWhereClause()(lines 52-75)
Problem
The normalization strips matching outer parentheses iteratively, then checks against a small set of known always-true patterns (1=1, true, empty string). Logically equivalen
Read the thread · 2026-02-28 · closed · 0 comments
Most recent
SQL injection via condition parameter in checkConstraintViolations
Summary
The condition parameter in checkConstraintViolations is validated by validateCondition() which uses the same insufficient denylist as WHERE clause validation, then interpolated directly into SQL.
Affected Files
src/tools/data-quality.ts—checkConstraintViolations()(lines 350-355)src/utils/sanitize.ts—validateCondition()(lines 136-154)
Problem
validateCondition() applies the same limited WHERE_DANGEROUS_PATTERNS denylist. The validated string is t
Read the thread · 2026-02-28 · closed · 0 comments
optimizeQuery ignores read-only ANALYZE restriction
Summary
The optimizeQuery tool always runs EXPLAIN (ANALYZE, ...) regardless of the server mode, bypassing the read-only protection that explainQuery correctly enforces.
Affected Files
src/tools/optimization.ts—optimizeQuery()(line 973)- Compare with
src/tools/query.ts—explainQueryTool()(lines 54-56) which correctly forcesanalyze=false
Problem
explainQueryTool checks connection.config.mode and forces analyze=false in read-only mode. optimizeQuery h
Read the thread · 2026-02-28 · closed · 0 comments
SQL injection via raw SET string in safeUpdate
Summary
When allowRawSet=true, the SET clause in safeUpdate is directly interpolated into the UPDATE query with no sanitization or parameterization.
Affected Files
src/tools/mutations.ts—safeUpdate()(lines 261-265)
Problem
When set is a string and allowRawSet=true, the value is assigned directly to setClause and embedded in the UPDATE query. No validation, escaping, or parameterization is applied to the string content.
While this is opt-in (disabled by default),
Read the thread · 2026-02-28 · closed · 0 comments
SQL injection via WHERE clause parameters across multiple tools
Summary
The where parameter accepted by multiple tools is validated using a denylist of regex patterns, then string-interpolated directly into SQL queries. The denylist is insufficient and allows several classes of injection.
Affected Files
src/utils/sanitize.ts—validateUserWhereClause()(lines 111-134)src/tools/mutations.ts—previewUpdate,previewDelete,safeUpdate,safeDeletesrc/tools/export.ts—exportTable,generateInsertStatements- `src/tools/tempo
Read the thread · 2026-02-28 · closed · 0 comments
Read-only mode bypass via CTE with writable main statement
Summary
The read-only mode enforcement in sanitizeQuery() can be bypassed when using CTEs (Common Table Expressions) combined with data-modifying main statements.
Affected Files
src/utils/sanitize.ts—sanitizeQuery()function (lines 42-74)
Problem
The operation check only inspects the first keyword of the query. When a query starts with WITH, it is allowed in read-only mode. The CTE_DATA_MODIFYING_PATTERN only checks the CTE body, not the main statement that follows. T
Read the thread · 2026-02-28 · closed · 0 comments
Parameter validation and documentation gaps
Weaknesses
Parameter validation inconsistencies:
- getHealthScore accepts nonexistent database names without error
- Some enum values aren't intuitive (had to guess cache not cache_hit_ratio)
Missing pg_stat_statements dependency - getSlowQueries fails silently without the extension
Documentation gaps - Had to discover valid enum values through trial and error
Row estimates show -1 - listTables shows rowEstimate: -1 for all tables (needs ANALYZE)
Verdict
Solid tool for data
Read the thread · 2025-12-22 · closed · 0 comments
Document safeUpdate raw SET opt‑in (allowRawSet) in tool metadata and README
We introduced allowRawSet to make safeUpdate reject raw SET strings by default. This is a backward‑compatibility change for clients that previously passed a string set. Update the MCP tool description and README examples to clearly indicate that raw SET strings now require allowRawSet=true. This helps agents and users understand the new safety behavior and avoid unexpected errors.
Read the thread · 2025-12-22 · closed · 0 comments
Security: Prevent data-modifying statements within Common Table Expressions (CTEs)
Background
The sanitizeQuery utility checks the first word of a query to ensure it is an allowed operation (e.g., SELECT, WITH). It also checks for semicolons followed by dangerous patterns to prevent multiple statements.
The Problem
PostgreSQL allows data-modifying statements (INSERT, UPDATE, DELETE) inside WITH clauses (CTEs). A query like:
WITH deleted AS (DELETE FROM users RETURNING *) SELECT * FROM deleted;
[Read the thread](https://github.com/bluwork/postgres-scout-mcp/issues/4) · 2025-12-20 · closed · 0 comments
The remaining reports are on [the project's issue tracker](https://github.com/bluwork/postgres-scout-mcp/issues).