@tejasanik/postgres-mcp-server 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +186 -10
- package/dist/db-manager/index.d.ts +7 -0
- package/dist/db-manager/index.d.ts.map +1 -0
- package/dist/db-manager/index.js +7 -0
- package/dist/db-manager/index.js.map +1 -0
- package/dist/db-manager/validation.d.ts +35 -0
- package/dist/db-manager/validation.d.ts.map +1 -0
- package/dist/db-manager/validation.js +54 -0
- package/dist/db-manager/validation.js.map +1 -0
- package/dist/db-manager.d.ts +175 -5
- package/dist/db-manager.d.ts.map +1 -1
- package/dist/db-manager.js +589 -26
- package/dist/db-manager.js.map +1 -1
- package/dist/index.js +141 -11
- package/dist/index.js.map +1 -1
- package/dist/tools/analysis-tools.d.ts.map +1 -1
- package/dist/tools/analysis-tools.js +53 -49
- package/dist/tools/analysis-tools.js.map +1 -1
- package/dist/tools/schema-tools.d.ts +40 -1
- package/dist/tools/schema-tools.d.ts.map +1 -1
- package/dist/tools/schema-tools.js +174 -92
- package/dist/tools/schema-tools.js.map +1 -1
- package/dist/tools/server-tools.d.ts +1 -0
- package/dist/tools/server-tools.d.ts.map +1 -1
- package/dist/tools/server-tools.js +10 -6
- package/dist/tools/server-tools.js.map +1 -1
- package/dist/tools/sql/utils/connection-utils.d.ts +79 -0
- package/dist/tools/sql/utils/connection-utils.d.ts.map +1 -0
- package/dist/tools/sql/utils/connection-utils.js +129 -0
- package/dist/tools/sql/utils/connection-utils.js.map +1 -0
- package/dist/tools/sql/utils/constants.d.ts +55 -0
- package/dist/tools/sql/utils/constants.d.ts.map +1 -0
- package/dist/tools/sql/utils/constants.js +55 -0
- package/dist/tools/sql/utils/constants.js.map +1 -0
- package/dist/tools/sql/utils/dry-run-utils.d.ts +31 -0
- package/dist/tools/sql/utils/dry-run-utils.d.ts.map +1 -0
- package/dist/tools/sql/utils/dry-run-utils.js +173 -0
- package/dist/tools/sql/utils/dry-run-utils.js.map +1 -0
- package/dist/tools/sql/utils/file-handler.d.ts +57 -0
- package/dist/tools/sql/utils/file-handler.d.ts.map +1 -0
- package/dist/tools/sql/utils/file-handler.js +150 -0
- package/dist/tools/sql/utils/file-handler.js.map +1 -0
- package/dist/tools/sql/utils/index.d.ts +12 -0
- package/dist/tools/sql/utils/index.d.ts.map +1 -0
- package/dist/tools/sql/utils/index.js +12 -0
- package/dist/tools/sql/utils/index.js.map +1 -0
- package/dist/tools/sql/utils/result-formatter.d.ts +94 -0
- package/dist/tools/sql/utils/result-formatter.d.ts.map +1 -0
- package/dist/tools/sql/utils/result-formatter.js +154 -0
- package/dist/tools/sql/utils/result-formatter.js.map +1 -0
- package/dist/tools/sql/utils/sql-parser.d.ts +125 -0
- package/dist/tools/sql/utils/sql-parser.d.ts.map +1 -0
- package/dist/tools/sql/utils/sql-parser.js +468 -0
- package/dist/tools/sql/utils/sql-parser.js.map +1 -0
- package/dist/tools/sql-tools.d.ts +21 -0
- package/dist/tools/sql-tools.d.ts.map +1 -1
- package/dist/tools/sql-tools.js +383 -532
- package/dist/tools/sql-tools.js.map +1 -1
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/retry.d.ts +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/validation.d.ts +45 -9
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +335 -72
- package/dist/utils/validation.js.map +1 -1
- package/package.json +9 -2
- package/dist/__tests__/analysis-tools.test.d.ts +0 -2
- package/dist/__tests__/analysis-tools.test.d.ts.map +0 -1
- package/dist/__tests__/analysis-tools.test.js +0 -294
- package/dist/__tests__/analysis-tools.test.js.map +0 -1
- package/dist/__tests__/db-manager.test.d.ts +0 -2
- package/dist/__tests__/db-manager.test.d.ts.map +0 -1
- package/dist/__tests__/db-manager.test.js +0 -410
- package/dist/__tests__/db-manager.test.js.map +0 -1
- package/dist/__tests__/mcp-server.test.d.ts +0 -13
- package/dist/__tests__/mcp-server.test.d.ts.map +0 -1
- package/dist/__tests__/mcp-server.test.js +0 -146
- package/dist/__tests__/mcp-server.test.js.map +0 -1
- package/dist/__tests__/schema-tools.test.d.ts +0 -2
- package/dist/__tests__/schema-tools.test.d.ts.map +0 -1
- package/dist/__tests__/schema-tools.test.js +0 -171
- package/dist/__tests__/schema-tools.test.js.map +0 -1
- package/dist/__tests__/server-tools.test.d.ts +0 -2
- package/dist/__tests__/server-tools.test.d.ts.map +0 -1
- package/dist/__tests__/server-tools.test.js +0 -113
- package/dist/__tests__/server-tools.test.js.map +0 -1
- package/dist/__tests__/sql-tools.test.d.ts +0 -2
- package/dist/__tests__/sql-tools.test.d.ts.map +0 -1
- package/dist/__tests__/sql-tools.test.js +0 -1912
- package/dist/__tests__/sql-tools.test.js.map +0 -1
- package/dist/__tests__/validation.test.d.ts +0 -2
- package/dist/__tests__/validation.test.d.ts.map +0 -1
- package/dist/__tests__/validation.test.js +0 -203
- package/dist/__tests__/validation.test.js.map +0 -1
package/dist/utils/validation.js
CHANGED
|
@@ -1,24 +1,168 @@
|
|
|
1
|
+
import { MAX_SQL_LENGTH_FOR_REGEX } from '../tools/sql/utils/constants.js';
|
|
2
|
+
/** Maximum identifier length in PostgreSQL */
|
|
3
|
+
const MAX_IDENTIFIER_LENGTH = 63;
|
|
4
|
+
/** Pattern for valid unquoted PostgreSQL identifier part */
|
|
5
|
+
const UNQUOTED_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_$]*$/;
|
|
6
|
+
/** Pattern for quoted identifier content (allows Unicode and most characters) */
|
|
7
|
+
// Using [^"]|"" instead of [^"]+|"" to avoid potential ReDoS from nested quantifiers
|
|
8
|
+
const QUOTED_IDENTIFIER_PATTERN = /^"(?:[^"]|"")*"$/;
|
|
9
|
+
/** SQL injection patterns that should never appear in identifiers */
|
|
10
|
+
const SQL_INJECTION_PATTERNS = [
|
|
11
|
+
/;/, // Statement terminator
|
|
12
|
+
/--/, // Line comment start
|
|
13
|
+
/\/\*/, // Block comment start
|
|
14
|
+
/\*\//, // Block comment end
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* Validates a single PostgreSQL identifier part (without schema).
|
|
18
|
+
* Supports both unquoted and quoted identifiers.
|
|
19
|
+
*
|
|
20
|
+
* @param part - The identifier part to validate
|
|
21
|
+
* @param fieldName - Field name for error messages
|
|
22
|
+
* @returns The validated identifier part
|
|
23
|
+
* @throws Error if the identifier is invalid
|
|
24
|
+
*/
|
|
25
|
+
function validateIdentifierPart(part, fieldName) {
|
|
26
|
+
if (!part || typeof part !== 'string') {
|
|
27
|
+
throw new Error(`${fieldName} is required and must be a string`);
|
|
28
|
+
}
|
|
29
|
+
// Check for SQL injection patterns
|
|
30
|
+
for (const pattern of SQL_INJECTION_PATTERNS) {
|
|
31
|
+
if (pattern.test(part)) {
|
|
32
|
+
throw new Error(`${fieldName} contains potentially dangerous SQL characters`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Handle quoted identifiers (allow Unicode)
|
|
36
|
+
if (part.startsWith('"') && part.endsWith('"')) {
|
|
37
|
+
if (!QUOTED_IDENTIFIER_PATTERN.test(part)) {
|
|
38
|
+
throw new Error(`${fieldName} has invalid quoted identifier syntax. Use "" to escape internal quotes.`);
|
|
39
|
+
}
|
|
40
|
+
// Extract content without quotes for length check
|
|
41
|
+
const content = part.slice(1, -1).replace(/""/g, '"');
|
|
42
|
+
if (content.length > MAX_IDENTIFIER_LENGTH) {
|
|
43
|
+
throw new Error(`${fieldName} must be ${MAX_IDENTIFIER_LENGTH} characters or less (excluding quotes)`);
|
|
44
|
+
}
|
|
45
|
+
return part;
|
|
46
|
+
}
|
|
47
|
+
// Unquoted identifier validation
|
|
48
|
+
if (part.length > MAX_IDENTIFIER_LENGTH) {
|
|
49
|
+
throw new Error(`${fieldName} must be ${MAX_IDENTIFIER_LENGTH} characters or less`);
|
|
50
|
+
}
|
|
51
|
+
if (!UNQUOTED_IDENTIFIER_PATTERN.test(part)) {
|
|
52
|
+
throw new Error(`${fieldName} contains invalid characters. Only letters, numbers, underscores, and dollar signs are allowed, ` +
|
|
53
|
+
`and it must start with a letter or underscore. Use double quotes for special characters or Unicode.`);
|
|
54
|
+
}
|
|
55
|
+
return part;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Gets the appropriate field name for a part in a qualified identifier.
|
|
59
|
+
* Extracted to avoid nested ternary operators.
|
|
60
|
+
*
|
|
61
|
+
* @param totalParts - Total number of parts in the identifier
|
|
62
|
+
* @param partIndex - Index of the current part (0-based)
|
|
63
|
+
* @param fieldName - Base field name for error messages
|
|
64
|
+
* @returns The appropriate part name for error messages
|
|
65
|
+
*/
|
|
66
|
+
function getPartName(totalParts, partIndex, fieldName) {
|
|
67
|
+
if (totalParts !== 2) {
|
|
68
|
+
return fieldName;
|
|
69
|
+
}
|
|
70
|
+
return partIndex === 0 ? `${fieldName} schema` : `${fieldName} name`;
|
|
71
|
+
}
|
|
1
72
|
/**
|
|
2
73
|
* Validates and sanitizes PostgreSQL identifiers (table names, column names, etc.)
|
|
3
|
-
*
|
|
74
|
+
* Supports schema-qualified names (schema.table) and quoted identifiers.
|
|
75
|
+
* Prevents SQL injection by validating identifier characters.
|
|
76
|
+
*
|
|
77
|
+
* @param identifier - The identifier to validate (e.g., "users", "public.users", '"My Table"')
|
|
78
|
+
* @param fieldName - Field name for error messages
|
|
79
|
+
* @param allowQualified - Whether to allow schema-qualified names (default: true)
|
|
80
|
+
* @returns The validated identifier
|
|
81
|
+
* @throws Error if the identifier is invalid
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* validateIdentifier('users', 'table') // 'users'
|
|
85
|
+
* validateIdentifier('public.users', 'table') // 'public.users'
|
|
86
|
+
* validateIdentifier('"My Table"', 'table') // '"My Table"'
|
|
87
|
+
* validateIdentifier('my_schema."Table"', 'table') // 'my_schema."Table"'
|
|
4
88
|
*/
|
|
5
|
-
export function validateIdentifier(identifier, fieldName) {
|
|
89
|
+
export function validateIdentifier(identifier, fieldName, allowQualified = true) {
|
|
6
90
|
if (!identifier || typeof identifier !== 'string') {
|
|
7
91
|
throw new Error(`${fieldName} is required and must be a string`);
|
|
8
92
|
}
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
throw new Error(`${fieldName}
|
|
93
|
+
const trimmed = identifier.trim();
|
|
94
|
+
// Split by unquoted dots (respecting quoted identifiers)
|
|
95
|
+
const parts = splitQualifiedIdentifier(trimmed);
|
|
96
|
+
if (parts.length === 0) {
|
|
97
|
+
throw new Error(`${fieldName} is required and must be a string`);
|
|
98
|
+
}
|
|
99
|
+
if (parts.length > 2) {
|
|
100
|
+
throw new Error(`${fieldName} has too many parts. Maximum format: schema.object`);
|
|
101
|
+
}
|
|
102
|
+
if (parts.length === 2 && !allowQualified) {
|
|
103
|
+
throw new Error(`${fieldName} cannot be schema-qualified. Provide just the object name.`);
|
|
104
|
+
}
|
|
105
|
+
// Validate each part
|
|
106
|
+
for (let i = 0; i < parts.length; i++) {
|
|
107
|
+
const partName = getPartName(parts.length, i, fieldName);
|
|
108
|
+
validateIdentifierPart(parts[i], partName);
|
|
109
|
+
}
|
|
110
|
+
return trimmed;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Splits a qualified identifier (e.g., "schema.table" or "schema"."table")
|
|
114
|
+
* into its parts, respecting quoted identifiers.
|
|
115
|
+
*
|
|
116
|
+
* @param identifier - The qualified identifier to split
|
|
117
|
+
* @returns Array of identifier parts
|
|
118
|
+
*/
|
|
119
|
+
function splitQualifiedIdentifier(identifier) {
|
|
120
|
+
const parts = [];
|
|
121
|
+
let current = '';
|
|
122
|
+
let inQuotes = false;
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < identifier.length) {
|
|
125
|
+
const char = identifier[i];
|
|
126
|
+
if (char === '"') {
|
|
127
|
+
if (inQuotes && identifier[i + 1] === '"') {
|
|
128
|
+
// Escaped quote inside quoted identifier
|
|
129
|
+
current += '""';
|
|
130
|
+
i += 2;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
inQuotes = !inQuotes;
|
|
134
|
+
current += char;
|
|
135
|
+
}
|
|
136
|
+
else if (char === '.' && !inQuotes) {
|
|
137
|
+
// Separator found
|
|
138
|
+
if (current.trim()) {
|
|
139
|
+
parts.push(current.trim());
|
|
140
|
+
}
|
|
141
|
+
current = '';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
current += char;
|
|
145
|
+
}
|
|
146
|
+
i++;
|
|
17
147
|
}
|
|
18
|
-
|
|
19
|
-
|
|
148
|
+
// Add the last part
|
|
149
|
+
if (current.trim()) {
|
|
150
|
+
parts.push(current.trim());
|
|
20
151
|
}
|
|
21
|
-
return
|
|
152
|
+
return parts;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Parses a qualified identifier into schema and object name.
|
|
156
|
+
*
|
|
157
|
+
* @param identifier - The identifier to parse (must be pre-validated)
|
|
158
|
+
* @returns Object with schema (optional) and name
|
|
159
|
+
*/
|
|
160
|
+
export function parseQualifiedIdentifier(identifier) {
|
|
161
|
+
const parts = splitQualifiedIdentifier(identifier);
|
|
162
|
+
if (parts.length === 2) {
|
|
163
|
+
return { schema: parts[0], name: parts[1] };
|
|
164
|
+
}
|
|
165
|
+
return { name: parts[0] || identifier };
|
|
22
166
|
}
|
|
23
167
|
/**
|
|
24
168
|
* Escapes a PostgreSQL identifier by doubling any internal double quotes
|
|
@@ -33,54 +177,126 @@ export function escapeIdentifier(identifier) {
|
|
|
33
177
|
return `"${identifier.replace(/"/g, '""')}"`;
|
|
34
178
|
}
|
|
35
179
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
180
|
+
* Write operations that should be blocked in read-only mode.
|
|
181
|
+
* Organized by category for maintainability.
|
|
38
182
|
*/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
183
|
+
const WRITE_OPERATIONS = [
|
|
184
|
+
// DML Operations
|
|
185
|
+
'INSERT',
|
|
186
|
+
'UPDATE',
|
|
187
|
+
'DELETE',
|
|
188
|
+
'MERGE', // SQL:2008 standard MERGE statement
|
|
189
|
+
'UPSERT', // PostgreSQL UPSERT pattern
|
|
190
|
+
// DDL Operations
|
|
191
|
+
'DROP',
|
|
192
|
+
'CREATE',
|
|
193
|
+
'ALTER',
|
|
194
|
+
'TRUNCATE',
|
|
195
|
+
'COMMENT ON', // Modifies metadata
|
|
196
|
+
// Security Operations
|
|
197
|
+
'GRANT',
|
|
198
|
+
'REVOKE',
|
|
199
|
+
'REASSIGN OWNED', // Ownership transfer
|
|
200
|
+
'SECURITY LABEL', // Security labels
|
|
201
|
+
// Maintenance Operations (with side effects)
|
|
202
|
+
'COPY', // Can write to files
|
|
203
|
+
'VACUUM',
|
|
204
|
+
'REINDEX',
|
|
205
|
+
'CLUSTER',
|
|
206
|
+
'ANALYZE', // Modifies statistics (can affect query plans)
|
|
207
|
+
'REFRESH MATERIALIZED VIEW',
|
|
208
|
+
// Lock Operations
|
|
209
|
+
'LOCK',
|
|
210
|
+
// Session State Operations
|
|
211
|
+
'DISCARD',
|
|
212
|
+
'RESET',
|
|
213
|
+
'SET ', // Note: space to avoid matching in column names
|
|
214
|
+
'SET LOCAL',
|
|
215
|
+
'SET SESSION',
|
|
216
|
+
// Code Execution
|
|
217
|
+
'DO', // Anonymous code blocks (no trailing space, \b handles boundary)
|
|
218
|
+
'CALL', // Stored procedures
|
|
219
|
+
'EXECUTE', // Dynamic SQL execution
|
|
220
|
+
// Transaction Control (shouldn't be in read-only queries)
|
|
221
|
+
'BEGIN',
|
|
222
|
+
'COMMIT',
|
|
223
|
+
'ROLLBACK',
|
|
224
|
+
'SAVEPOINT',
|
|
225
|
+
'RELEASE SAVEPOINT',
|
|
226
|
+
// PostgreSQL Extensions
|
|
227
|
+
'LOAD', // Load shared library
|
|
228
|
+
'IMPORT FOREIGN SCHEMA',
|
|
229
|
+
'CREATE SERVER',
|
|
230
|
+
'CREATE FOREIGN',
|
|
231
|
+
'NOTIFY', // Send notification
|
|
232
|
+
'LISTEN', // Subscribe to notifications
|
|
233
|
+
'UNLISTEN', // Unsubscribe from notifications
|
|
234
|
+
];
|
|
235
|
+
/**
|
|
236
|
+
* Functions that could have side effects or security implications.
|
|
237
|
+
*/
|
|
238
|
+
const DANGEROUS_FUNCTIONS = [
|
|
239
|
+
// Large Object Functions
|
|
240
|
+
'LO_IMPORT',
|
|
241
|
+
'LO_EXPORT',
|
|
242
|
+
'LO_UNLINK',
|
|
243
|
+
'LO_CREATE',
|
|
244
|
+
'LO_OPEN',
|
|
245
|
+
'LO_WRITE',
|
|
246
|
+
'LO_PUT',
|
|
247
|
+
// File System Functions
|
|
248
|
+
'PG_READ_FILE',
|
|
249
|
+
'PG_READ_BINARY_FILE',
|
|
250
|
+
'PG_WRITE_FILE',
|
|
251
|
+
'PG_FILE_WRITE',
|
|
252
|
+
'PG_FILE_UNLINK',
|
|
253
|
+
'PG_FILE_RENAME',
|
|
254
|
+
// Remote Connection Functions
|
|
255
|
+
'DBLINK_EXEC',
|
|
256
|
+
'DBLINK',
|
|
257
|
+
'DBLINK_CONNECT',
|
|
258
|
+
'DBLINK_SEND_QUERY',
|
|
259
|
+
// Copy Functions
|
|
260
|
+
'COPY_TO',
|
|
261
|
+
'COPY_FROM',
|
|
262
|
+
// System Administration
|
|
263
|
+
'PG_TERMINATE_BACKEND',
|
|
264
|
+
'PG_CANCEL_BACKEND',
|
|
265
|
+
'PG_RELOAD_CONF',
|
|
266
|
+
'PG_ROTATE_LOGFILE',
|
|
267
|
+
'PG_SWITCH_WAL',
|
|
268
|
+
'PG_SWITCH_XLOG',
|
|
269
|
+
// Sequence Functions (modify state even in rollback)
|
|
270
|
+
'NEXTVAL',
|
|
271
|
+
'SETVAL',
|
|
272
|
+
'CURRVAL', // Only dangerous if called after NEXTVAL
|
|
273
|
+
// Advisory Lock Functions (can affect other sessions)
|
|
274
|
+
'PG_ADVISORY_LOCK',
|
|
275
|
+
'PG_ADVISORY_UNLOCK',
|
|
276
|
+
'PG_TRY_ADVISORY_LOCK',
|
|
277
|
+
];
|
|
278
|
+
/**
|
|
279
|
+
* Normalizes SQL for analysis by removing comments and extra whitespace.
|
|
280
|
+
*/
|
|
281
|
+
function normalizeSqlForAnalysis(sql) {
|
|
282
|
+
return sql
|
|
283
|
+
.replace(/--[^\n]*/g, '') // Remove single-line comments
|
|
284
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments (non-greedy, safe pattern)
|
|
285
|
+
.replace(/\s+/g, ' ') // Normalize whitespace
|
|
51
286
|
.trim()
|
|
52
287
|
.toUpperCase();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
'
|
|
61
|
-
'TRUNCATE',
|
|
62
|
-
'GRANT',
|
|
63
|
-
'REVOKE',
|
|
64
|
-
'COPY',
|
|
65
|
-
'VACUUM',
|
|
66
|
-
'REINDEX',
|
|
67
|
-
'CLUSTER',
|
|
68
|
-
'REFRESH MATERIALIZED VIEW',
|
|
69
|
-
'LOCK',
|
|
70
|
-
'DISCARD',
|
|
71
|
-
'RESET',
|
|
72
|
-
'SET ', // Note: space to avoid matching in column names
|
|
73
|
-
'DO ', // Anonymous code blocks
|
|
74
|
-
'CALL', // Stored procedures
|
|
75
|
-
];
|
|
76
|
-
// Check if any write operation appears as a keyword (word boundary check)
|
|
77
|
-
for (const op of writeOperations) {
|
|
78
|
-
// Check at start or after common statement separators
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Checks if SQL contains any write operations.
|
|
291
|
+
* Uses ReDoS-safe patterns with bounded whitespace.
|
|
292
|
+
*/
|
|
293
|
+
function checkWriteOperations(normalizedSql) {
|
|
294
|
+
for (const op of WRITE_OPERATIONS) {
|
|
295
|
+
const escapedOp = op.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
79
296
|
const patterns = [
|
|
80
|
-
new RegExp(`^${
|
|
81
|
-
new RegExp(`\\(\\s
|
|
82
|
-
new RegExp(`;\\s
|
|
83
|
-
new RegExp(`\\bWITH\\b.*\\bAS\\s*\\(\\s*${op}\\b`, 's'), // In CTE
|
|
297
|
+
new RegExp(`^${escapedOp}\\b`), // At start
|
|
298
|
+
new RegExp(`\\(\\s{0,10}${escapedOp}\\b`), // After opening paren
|
|
299
|
+
new RegExp(`;\\s{0,10}${escapedOp}\\b`), // After semicolon
|
|
84
300
|
];
|
|
85
301
|
for (const pattern of patterns) {
|
|
86
302
|
if (pattern.test(normalizedSql)) {
|
|
@@ -88,32 +304,79 @@ export function isReadOnlySql(sql) {
|
|
|
88
304
|
}
|
|
89
305
|
}
|
|
90
306
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Checks for data-modifying CTEs (WITH ... AS (INSERT/UPDATE/DELETE)).
|
|
311
|
+
*/
|
|
312
|
+
function checkCteWriteOperations(normalizedSql) {
|
|
313
|
+
if (!/\bWITH\b/.test(normalizedSql)) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
for (const op of ['INSERT', 'UPDATE', 'DELETE', 'MERGE']) {
|
|
317
|
+
if (new RegExp(`\\bAS\\s{0,10}\\(\\s{0,10}${op}\\b`).test(normalizedSql)) {
|
|
318
|
+
return { isReadOnly: false, reason: `Write operation '${op}' in CTE detected` };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Checks for dangerous function calls that could have side effects.
|
|
325
|
+
*/
|
|
326
|
+
function checkDangerousFunctions(normalizedSql) {
|
|
327
|
+
for (const func of DANGEROUS_FUNCTIONS) {
|
|
328
|
+
const escapedFunc = func.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
329
|
+
if (new RegExp(`\\b${escapedFunc}\\s{0,10}\\(`).test(normalizedSql)) {
|
|
104
330
|
return { isReadOnly: false, reason: `Dangerous function '${func}' detected` };
|
|
105
331
|
}
|
|
106
332
|
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Validates SQL for read-only operations more thoroughly.
|
|
337
|
+
* Uses ReDoS-safe patterns and comprehensive operation detection.
|
|
338
|
+
*
|
|
339
|
+
* @param sql - The SQL string to validate
|
|
340
|
+
* @returns Object with isReadOnly flag and optional reason
|
|
341
|
+
*/
|
|
342
|
+
export function isReadOnlySql(sql) {
|
|
343
|
+
if (!sql || typeof sql !== 'string') {
|
|
344
|
+
return { isReadOnly: false, reason: 'SQL is required' };
|
|
345
|
+
}
|
|
346
|
+
if (sql.length > MAX_SQL_LENGTH_FOR_REGEX) {
|
|
347
|
+
return {
|
|
348
|
+
isReadOnly: false,
|
|
349
|
+
reason: `SQL too large for safe validation (${sql.length} chars, max ${MAX_SQL_LENGTH_FOR_REGEX}). Review manually.`,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
const normalizedSql = normalizeSqlForAnalysis(sql);
|
|
353
|
+
// Check each category of dangerous operations
|
|
354
|
+
const writeCheck = checkWriteOperations(normalizedSql);
|
|
355
|
+
if (writeCheck)
|
|
356
|
+
return writeCheck;
|
|
357
|
+
const cteCheck = checkCteWriteOperations(normalizedSql);
|
|
358
|
+
if (cteCheck)
|
|
359
|
+
return cteCheck;
|
|
360
|
+
const funcCheck = checkDangerousFunctions(normalizedSql);
|
|
361
|
+
if (funcCheck)
|
|
362
|
+
return funcCheck;
|
|
107
363
|
return { isReadOnly: true };
|
|
108
364
|
}
|
|
109
365
|
/**
|
|
110
|
-
* Validates that a
|
|
366
|
+
* Validates that a value is a positive integer within acceptable bounds.
|
|
367
|
+
*
|
|
368
|
+
* @param value - The value to validate (can be number, string, or undefined/null)
|
|
369
|
+
* @param fieldName - Name of the field for error messages
|
|
370
|
+
* @param min - Minimum allowed value (default: 1)
|
|
371
|
+
* @param max - Maximum allowed value (default: 10000)
|
|
372
|
+
* @returns The validated integer value
|
|
373
|
+
* @throws Error if value is not a valid integer within bounds
|
|
111
374
|
*/
|
|
112
375
|
export function validatePositiveInteger(value, fieldName, min = 1, max = 10000) {
|
|
113
376
|
if (value === undefined || value === null) {
|
|
114
377
|
return min;
|
|
115
378
|
}
|
|
116
|
-
const num = parseInt(value, 10);
|
|
379
|
+
const num = typeof value === 'number' ? value : parseInt(String(value), 10);
|
|
117
380
|
if (isNaN(num) || num < min || num > max) {
|
|
118
381
|
throw new Error(`${fieldName} must be an integer between ${min} and ${max}`);
|
|
119
382
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tejasanik/postgres-mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A Model Context Protocol (MCP) server for PostgreSQL database management and analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"dev": "ts-node src/index.ts",
|
|
15
15
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
16
16
|
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch",
|
|
17
|
+
"lint": "eslint src --ignore-pattern '__tests__'",
|
|
18
|
+
"lint:fix": "eslint src --ignore-pattern '__tests__' --fix",
|
|
17
19
|
"prepare": "npm run build",
|
|
18
20
|
"prepublishOnly": "npm run build && npm test"
|
|
19
21
|
},
|
|
@@ -39,9 +41,14 @@
|
|
|
39
41
|
"@types/node": "^22.10.2",
|
|
40
42
|
"@types/pg": "^8.11.10",
|
|
41
43
|
"@types/uuid": "^10.0.0",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^8.51.0",
|
|
45
|
+
"@typescript-eslint/parser": "^8.51.0",
|
|
46
|
+
"eslint": "^9.39.2",
|
|
47
|
+
"eslint-plugin-sonarjs": "^3.0.5",
|
|
42
48
|
"jest": "^29.7.0",
|
|
43
49
|
"ts-jest": "^29.2.5",
|
|
44
|
-
"typescript": "^5.7.2"
|
|
50
|
+
"typescript": "^5.7.2",
|
|
51
|
+
"typescript-eslint": "^8.51.0"
|
|
45
52
|
},
|
|
46
53
|
"engines": {
|
|
47
54
|
"node": ">=18.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-tools.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/analysis-tools.test.ts"],"names":[],"mappings":""}
|