mcp-database-inspector 2.0.1

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.
Files changed (105) hide show
  1. package/README.md +197 -0
  2. package/dist/database/connection.d.ts +13 -0
  3. package/dist/database/connection.d.ts.map +1 -0
  4. package/dist/database/connection.js +155 -0
  5. package/dist/database/connection.js.map +1 -0
  6. package/dist/database/manager.d.ts +28 -0
  7. package/dist/database/manager.d.ts.map +1 -0
  8. package/dist/database/manager.js +621 -0
  9. package/dist/database/manager.js.map +1 -0
  10. package/dist/database/postgres-connection.d.ts +10 -0
  11. package/dist/database/postgres-connection.d.ts.map +1 -0
  12. package/dist/database/postgres-connection.js +113 -0
  13. package/dist/database/postgres-connection.js.map +1 -0
  14. package/dist/database/types.d.ts +84 -0
  15. package/dist/database/types.d.ts.map +1 -0
  16. package/dist/database/types.js +6 -0
  17. package/dist/database/types.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +120 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/server.d.ts +14 -0
  23. package/dist/server.d.ts.map +1 -0
  24. package/dist/server.js +186 -0
  25. package/dist/server.js.map +1 -0
  26. package/dist/test-defaults.d.ts +2 -0
  27. package/dist/test-defaults.d.ts.map +1 -0
  28. package/dist/test-defaults.js +57 -0
  29. package/dist/test-defaults.js.map +1 -0
  30. package/dist/tools/analyze-query.d.ts +27 -0
  31. package/dist/tools/analyze-query.d.ts.map +1 -0
  32. package/dist/tools/analyze-query.js +71 -0
  33. package/dist/tools/analyze-query.js.map +1 -0
  34. package/dist/tools/execute-query.d.ts +33 -0
  35. package/dist/tools/execute-query.d.ts.map +1 -0
  36. package/dist/tools/execute-query.js +57 -0
  37. package/dist/tools/execute-query.js.map +1 -0
  38. package/dist/tools/get-foreign-keys.d.ts +38 -0
  39. package/dist/tools/get-foreign-keys.d.ts.map +1 -0
  40. package/dist/tools/get-foreign-keys.js +391 -0
  41. package/dist/tools/get-foreign-keys.js.map +1 -0
  42. package/dist/tools/get-indexes.d.ts +38 -0
  43. package/dist/tools/get-indexes.d.ts.map +1 -0
  44. package/dist/tools/get-indexes.js +472 -0
  45. package/dist/tools/get-indexes.js.map +1 -0
  46. package/dist/tools/information-schema-query.d.ts +33 -0
  47. package/dist/tools/information-schema-query.d.ts.map +1 -0
  48. package/dist/tools/information-schema-query.js +76 -0
  49. package/dist/tools/information-schema-query.js.map +1 -0
  50. package/dist/tools/inspect-table.d.ts +38 -0
  51. package/dist/tools/inspect-table.d.ts.map +1 -0
  52. package/dist/tools/inspect-table.js +351 -0
  53. package/dist/tools/inspect-table.js.map +1 -0
  54. package/dist/tools/list-databases.d.ts +14 -0
  55. package/dist/tools/list-databases.d.ts.map +1 -0
  56. package/dist/tools/list-databases.js +83 -0
  57. package/dist/tools/list-databases.js.map +1 -0
  58. package/dist/tools/list-tables.d.ts +19 -0
  59. package/dist/tools/list-tables.d.ts.map +1 -0
  60. package/dist/tools/list-tables.js +130 -0
  61. package/dist/tools/list-tables.js.map +1 -0
  62. package/dist/utils/errors.d.ts +32 -0
  63. package/dist/utils/errors.d.ts.map +1 -0
  64. package/dist/utils/errors.js +98 -0
  65. package/dist/utils/errors.js.map +1 -0
  66. package/dist/utils/logger.d.ts +28 -0
  67. package/dist/utils/logger.d.ts.map +1 -0
  68. package/dist/utils/logger.js +132 -0
  69. package/dist/utils/logger.js.map +1 -0
  70. package/dist/validators/input-validator.d.ts +76 -0
  71. package/dist/validators/input-validator.d.ts.map +1 -0
  72. package/dist/validators/input-validator.js +295 -0
  73. package/dist/validators/input-validator.js.map +1 -0
  74. package/dist/validators/query-validator.d.ts +19 -0
  75. package/dist/validators/query-validator.d.ts.map +1 -0
  76. package/dist/validators/query-validator.js +229 -0
  77. package/dist/validators/query-validator.js.map +1 -0
  78. package/enhanced_sql_prompt.md +324 -0
  79. package/examples/claude-config.json +23 -0
  80. package/examples/roo-config.json +16 -0
  81. package/package.json +42 -0
  82. package/src/database/connection.ts +165 -0
  83. package/src/database/manager.ts +682 -0
  84. package/src/database/postgres-connection.ts +123 -0
  85. package/src/database/types.ts +93 -0
  86. package/src/index.ts +136 -0
  87. package/src/server.ts +254 -0
  88. package/src/test-defaults.ts +63 -0
  89. package/src/tools/analyze-query.test.ts +100 -0
  90. package/src/tools/analyze-query.ts +112 -0
  91. package/src/tools/execute-query.ts +91 -0
  92. package/src/tools/get-foreign-keys.test.ts +51 -0
  93. package/src/tools/get-foreign-keys.ts +488 -0
  94. package/src/tools/get-indexes.test.ts +51 -0
  95. package/src/tools/get-indexes.ts +570 -0
  96. package/src/tools/information-schema-query.ts +125 -0
  97. package/src/tools/inspect-table.test.ts +59 -0
  98. package/src/tools/inspect-table.ts +440 -0
  99. package/src/tools/list-databases.ts +119 -0
  100. package/src/tools/list-tables.ts +181 -0
  101. package/src/utils/errors.ts +103 -0
  102. package/src/utils/logger.ts +158 -0
  103. package/src/validators/input-validator.ts +318 -0
  104. package/src/validators/query-validator.ts +267 -0
  105. package/tsconfig.json +30 -0
@@ -0,0 +1,295 @@
1
+ import { z } from 'zod';
2
+ export class InputValidator {
3
+ // Schema for database connection URLs
4
+ static connectionUrlSchema = z.string()
5
+ .url()
6
+ .refine(url => url.startsWith('mysql://') || url.startsWith('postgresql://') || url.startsWith('postgres://'), {
7
+ message: 'URL must start with mysql://, postgresql://, or postgres://'
8
+ })
9
+ .refine(url => {
10
+ try {
11
+ const parsed = new URL(url);
12
+ return parsed.hostname && parsed.username && parsed.password;
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }, {
18
+ message: 'URL must contain hostname, username, and password'
19
+ });
20
+ // Schema for database names
21
+ static databaseNameSchema = z.string()
22
+ .min(1, 'Database name cannot be empty')
23
+ .max(64, 'Database name cannot exceed 64 characters')
24
+ .regex(/^[a-zA-Z_][a-zA-Z0-9_$-]*$/, 'Invalid database name format');
25
+ // Schema for table names
26
+ static tableNameSchema = z.string()
27
+ .min(1, 'Table name cannot be empty')
28
+ .max(64, 'Table name cannot exceed 64 characters')
29
+ .regex(/^[a-zA-Z_][a-zA-Z0-9_$-]*$|^`[^`]+`$/, 'Invalid table name format');
30
+ // Schema for column names
31
+ static columnNameSchema = z.string()
32
+ .min(1, 'Column name cannot be empty')
33
+ .max(64, 'Column name cannot exceed 64 characters')
34
+ .regex(/^[a-zA-Z_][a-zA-Z0-9_$-]*$|^`[^`]+`$/, 'Invalid column name format');
35
+ // Schema for general text input
36
+ static textInputSchema = z.string()
37
+ .max(10000, 'Input too long')
38
+ .refine(text => !text.includes('\0'), {
39
+ message: 'Input cannot contain null bytes'
40
+ });
41
+ /**
42
+ * Validate a connection URL
43
+ */
44
+ static validateConnectionUrl(url) {
45
+ try {
46
+ this.connectionUrlSchema.parse(url);
47
+ return { isValid: true };
48
+ }
49
+ catch (error) {
50
+ if (error instanceof z.ZodError) {
51
+ return {
52
+ isValid: false,
53
+ error: error.issues.map(e => e.message).join(', ')
54
+ };
55
+ }
56
+ return {
57
+ isValid: false,
58
+ error: 'Invalid connection URL format'
59
+ };
60
+ }
61
+ }
62
+ /**
63
+ * Validate a database name
64
+ */
65
+ static validateDatabaseName(name) {
66
+ try {
67
+ this.databaseNameSchema.parse(name);
68
+ return { isValid: true };
69
+ }
70
+ catch (error) {
71
+ if (error instanceof z.ZodError) {
72
+ return {
73
+ isValid: false,
74
+ error: error.issues.map(e => e.message).join(', ')
75
+ };
76
+ }
77
+ return {
78
+ isValid: false,
79
+ error: 'Invalid database name'
80
+ };
81
+ }
82
+ }
83
+ /**
84
+ * Validate a table name
85
+ */
86
+ static validateTableName(name) {
87
+ try {
88
+ this.tableNameSchema.parse(name);
89
+ return { isValid: true };
90
+ }
91
+ catch (error) {
92
+ if (error instanceof z.ZodError) {
93
+ return {
94
+ isValid: false,
95
+ error: error.issues.map(e => e.message).join(', ')
96
+ };
97
+ }
98
+ return {
99
+ isValid: false,
100
+ error: 'Invalid table name'
101
+ };
102
+ }
103
+ }
104
+ /**
105
+ * Validate a column name
106
+ */
107
+ static validateColumnName(name) {
108
+ try {
109
+ this.columnNameSchema.parse(name);
110
+ return { isValid: true };
111
+ }
112
+ catch (error) {
113
+ if (error instanceof z.ZodError) {
114
+ return {
115
+ isValid: false,
116
+ error: error.issues.map(e => e.message).join(', ')
117
+ };
118
+ }
119
+ return {
120
+ isValid: false,
121
+ error: 'Invalid column name'
122
+ };
123
+ }
124
+ }
125
+ /**
126
+ * Validate text input
127
+ */
128
+ static validateTextInput(text) {
129
+ try {
130
+ this.textInputSchema.parse(text);
131
+ return { isValid: true };
132
+ }
133
+ catch (error) {
134
+ if (error instanceof z.ZodError) {
135
+ return {
136
+ isValid: false,
137
+ error: error.issues.map(e => e.message).join(', ')
138
+ };
139
+ }
140
+ return {
141
+ isValid: false,
142
+ error: 'Invalid text input'
143
+ };
144
+ }
145
+ }
146
+ /**
147
+ * Sanitize string input by removing dangerous characters
148
+ */
149
+ static sanitizeString(input) {
150
+ if (!input)
151
+ return '';
152
+ return input
153
+ // Remove null bytes
154
+ .replace(/\0/g, '')
155
+ // Remove control characters except tab, newline, carriage return
156
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
157
+ // Trim whitespace
158
+ .trim();
159
+ }
160
+ /**
161
+ * Escape MySQL identifiers (table names, column names)
162
+ */
163
+ static escapeIdentifier(identifier) {
164
+ if (!identifier)
165
+ return '';
166
+ // If already quoted, return as is
167
+ if (identifier.startsWith('`') && identifier.endsWith('`')) {
168
+ return identifier;
169
+ }
170
+ // Remove any existing backticks and escape them
171
+ const cleaned = identifier.replace(/`/g, '``');
172
+ return `\`${cleaned}\``;
173
+ }
174
+ /**
175
+ * Validate tool arguments based on schema
176
+ */
177
+ static validateToolArgs(args, schema) {
178
+ try {
179
+ const data = schema.parse(args);
180
+ return { isValid: true, data };
181
+ }
182
+ catch (error) {
183
+ if (error instanceof z.ZodError) {
184
+ return {
185
+ isValid: false,
186
+ error: `Invalid arguments: ${error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`
187
+ };
188
+ }
189
+ return {
190
+ isValid: false,
191
+ error: 'Invalid arguments format'
192
+ };
193
+ }
194
+ }
195
+ /**
196
+ * Validate that a string represents a valid number
197
+ */
198
+ static validateNumeric(value, options) {
199
+ const num = Number(value);
200
+ if (isNaN(num)) {
201
+ return { isValid: false, error: 'Value must be a valid number' };
202
+ }
203
+ if (options?.integer && !Number.isInteger(num)) {
204
+ return { isValid: false, error: 'Value must be an integer' };
205
+ }
206
+ if (options?.min !== undefined && num < options.min) {
207
+ return { isValid: false, error: `Value must be at least ${options.min}` };
208
+ }
209
+ if (options?.max !== undefined && num > options.max) {
210
+ return { isValid: false, error: `Value must be at most ${options.max}` };
211
+ }
212
+ return { isValid: true };
213
+ }
214
+ /**
215
+ * Validate an array of values
216
+ */
217
+ static validateArray(values, itemValidator) {
218
+ if (!Array.isArray(values)) {
219
+ return { isValid: false, error: 'Value must be an array' };
220
+ }
221
+ const validatedItems = [];
222
+ const errors = [];
223
+ for (let i = 0; i < values.length; i++) {
224
+ const result = itemValidator(values[i]);
225
+ if (result.isValid && result.data !== undefined) {
226
+ validatedItems.push(result.data);
227
+ }
228
+ else {
229
+ errors.push(`Item ${i}: ${result.error || 'Validation failed'}`);
230
+ }
231
+ }
232
+ if (errors.length > 0) {
233
+ return { isValid: false, error: errors.join(', ') };
234
+ }
235
+ return { isValid: true, data: validatedItems };
236
+ }
237
+ /**
238
+ * Validate email format (for potential user management features)
239
+ */
240
+ static validateEmail(email) {
241
+ const emailSchema = z.string().email();
242
+ try {
243
+ emailSchema.parse(email);
244
+ return { isValid: true };
245
+ }
246
+ catch (error) {
247
+ return { isValid: false, error: 'Invalid email format' };
248
+ }
249
+ }
250
+ /**
251
+ * Validate URL format
252
+ */
253
+ static validateUrl(url) {
254
+ const urlSchema = z.string().url();
255
+ try {
256
+ urlSchema.parse(url);
257
+ return { isValid: true };
258
+ }
259
+ catch (error) {
260
+ return { isValid: false, error: 'Invalid URL format' };
261
+ }
262
+ }
263
+ /**
264
+ * Check if a string contains only safe characters for logging
265
+ */
266
+ static isSafeForLogging(text) {
267
+ // Check for sensitive patterns that shouldn't be logged
268
+ const sensitivePatterns = [
269
+ /password\s*[=:]\s*[^\s&]+/gi,
270
+ /pwd\s*[=:]\s*[^\s&]+/gi,
271
+ /secret\s*[=:]\s*[^\s&]+/gi,
272
+ /token\s*[=:]\s*[^\s&]+/gi,
273
+ /key\s*[=:]\s*[^\s&]+/gi,
274
+ /(mysql|postgresql?):\/\/[^@]+:[^@]+@/gi, // Connection strings with credentials
275
+ ];
276
+ return !sensitivePatterns.some(pattern => pattern.test(text));
277
+ }
278
+ /**
279
+ * Sanitize text for safe logging by masking sensitive information
280
+ */
281
+ static sanitizeForLogging(text) {
282
+ if (!text)
283
+ return '';
284
+ return text
285
+ // Mask passwords in URLs
286
+ .replace(/((?:mysql|postgresql?):\/\/[^:]+:)[^@]+(@)/gi, '$1***$2')
287
+ // Mask password parameters
288
+ .replace(/(password\s*[=:]\s*)[^\s&]+/gi, '$1***')
289
+ .replace(/(pwd\s*[=:]\s*)[^\s&]+/gi, '$1***')
290
+ .replace(/(secret\s*[=:]\s*)[^\s&]+/gi, '$1***')
291
+ .replace(/(token\s*[=:]\s*)[^\s&]+/gi, '$1***')
292
+ .replace(/(key\s*[=:]\s*)[^\s&]+/gi, '$1***');
293
+ }
294
+ }
295
+ //# sourceMappingURL=input-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/validators/input-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { DatabaseType, ValidationResult } from '../database/types.js';
2
+ export declare class QueryValidator {
3
+ private static readonly FORBIDDEN_KEYWORDS;
4
+ private static readonly ALLOWED_KEYWORDS;
5
+ private static readonly FORBIDDEN_FUNCTIONS;
6
+ static validateQuery(query: string, type?: DatabaseType): ValidationResult;
7
+ private static normalizeQuery;
8
+ private static checkForbiddenKeywords;
9
+ private static checkForbiddenFunctions;
10
+ private static checkAllowedStart;
11
+ private static checkSqlInjectionPatterns;
12
+ private static checkSuspiciousPatterns;
13
+ private static getWarnings;
14
+ static validateIdentifier(identifier: string): ValidationResult;
15
+ static sanitizeInput(input: string): string;
16
+ static isSimpleReadQuery(query: string): boolean;
17
+ static getQueryComplexity(query: string): 'low' | 'medium' | 'high';
18
+ }
19
+ //# sourceMappingURL=query-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-validator.d.ts","sourceRoot":"","sources":["../../src/validators/query-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEtE,qBAAa,cAAc;IAEzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAQxC;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAGtC;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAIzC;IAEF,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,YAAiC,GAAG,gBAAgB;IA8C9F,OAAO,CAAC,MAAM,CAAC,cAAc;IAU7B,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAcrC,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAYtC,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAahC,OAAO,CAAC,MAAM,CAAC,yBAAyB;IA0BxC,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAqBtC,OAAO,CAAC,MAAM,CAAC,WAAW;IAyB1B,MAAM,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB;IA+B/D,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAW3C,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQhD,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM;CAsBpE"}
@@ -0,0 +1,229 @@
1
+ import { DatabaseType } from '../database/types.js';
2
+ export class QueryValidator {
3
+ // Keywords that are forbidden in queries
4
+ static FORBIDDEN_KEYWORDS = [
5
+ 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE',
6
+ 'ALTER', 'TRUNCATE', 'REPLACE', 'MERGE', 'CALL',
7
+ 'EXEC', 'EXECUTE', 'LOAD', 'IMPORT', 'BULK',
8
+ 'GRANT', 'REVOKE', 'SET', 'USE', 'START',
9
+ 'BEGIN', 'COMMIT', 'ROLLBACK', 'SAVEPOINT',
10
+ 'LOCK', 'UNLOCK', 'FLUSH', 'RESET', 'PURGE',
11
+ 'KILL', 'SHUTDOWN', 'RESTART', 'COPY'
12
+ ];
13
+ // Allowed keywords for read-only operations
14
+ static ALLOWED_KEYWORDS = [
15
+ 'SELECT', 'SHOW', 'DESCRIBE', 'DESC', 'EXPLAIN',
16
+ 'ANALYZE', 'CHECK', 'CHECKSUM', 'OPTIMIZE', 'WITH', 'VALUES'
17
+ ];
18
+ // Dangerous functions that should be blocked
19
+ static FORBIDDEN_FUNCTIONS = [
20
+ 'LOAD_FILE', 'INTO OUTFILE', 'INTO DUMPFILE',
21
+ 'SYSTEM', 'USER_DEFINED_FUNCTION', 'BENCHMARK',
22
+ 'PG_READ_FILE', 'PG_LS_DIR', 'PG_EXECUTE'
23
+ ];
24
+ static validateQuery(query, type = DatabaseType.MySQL) {
25
+ if (!query || query.trim().length === 0) {
26
+ return {
27
+ isValid: false,
28
+ error: 'Query cannot be empty'
29
+ };
30
+ }
31
+ const normalizedQuery = this.normalizeQuery(query);
32
+ // Check for forbidden keywords
33
+ const forbiddenCheck = this.checkForbiddenKeywords(normalizedQuery);
34
+ if (!forbiddenCheck.isValid) {
35
+ return forbiddenCheck;
36
+ }
37
+ // Check for forbidden functions
38
+ const functionCheck = this.checkForbiddenFunctions(normalizedQuery);
39
+ if (!functionCheck.isValid) {
40
+ return functionCheck;
41
+ }
42
+ // Check if query starts with an allowed keyword
43
+ const allowedCheck = this.checkAllowedStart(normalizedQuery);
44
+ if (!allowedCheck.isValid) {
45
+ return allowedCheck;
46
+ }
47
+ // Check for SQL injection patterns
48
+ const injectionCheck = this.checkSqlInjectionPatterns(normalizedQuery, type);
49
+ if (!injectionCheck.isValid) {
50
+ return injectionCheck;
51
+ }
52
+ // Check for suspicious patterns
53
+ const suspiciousCheck = this.checkSuspiciousPatterns(normalizedQuery);
54
+ if (!suspiciousCheck.isValid) {
55
+ return suspiciousCheck;
56
+ }
57
+ return {
58
+ isValid: true,
59
+ warnings: this.getWarnings(normalizedQuery)
60
+ };
61
+ }
62
+ static normalizeQuery(query) {
63
+ // Remove comments and normalize whitespace
64
+ return query
65
+ .replace(/--[^\r\n]*/g, '') // Remove -- comments
66
+ .replace(/\/\*[\s\S]*?\*\//g, '') // Remove /* */ comments
67
+ .replace(/\s+/g, ' ') // Normalize whitespace
68
+ .trim()
69
+ .toUpperCase();
70
+ }
71
+ static checkForbiddenKeywords(query) {
72
+ for (const keyword of this.FORBIDDEN_KEYWORDS) {
73
+ // Use word boundaries to avoid false positives
74
+ const regex = new RegExp(`\\b${keyword}\\b`, 'i');
75
+ if (regex.test(query)) {
76
+ return {
77
+ isValid: false,
78
+ error: `Forbidden keyword detected: ${keyword}. Only read-only operations are allowed.`
79
+ };
80
+ }
81
+ }
82
+ return { isValid: true };
83
+ }
84
+ static checkForbiddenFunctions(query) {
85
+ for (const func of this.FORBIDDEN_FUNCTIONS) {
86
+ if (query.includes(func)) {
87
+ return {
88
+ isValid: false,
89
+ error: `Forbidden function detected: ${func}. This function is not allowed for security reasons.`
90
+ };
91
+ }
92
+ }
93
+ return { isValid: true };
94
+ }
95
+ static checkAllowedStart(query) {
96
+ const firstWord = query.split(' ')[0];
97
+ if (!this.ALLOWED_KEYWORDS.includes(firstWord)) {
98
+ return {
99
+ isValid: false,
100
+ error: `Query must start with one of: ${this.ALLOWED_KEYWORDS.join(', ')}`
101
+ };
102
+ }
103
+ return { isValid: true };
104
+ }
105
+ static checkSqlInjectionPatterns(query, type) {
106
+ const suspiciousPatterns = [
107
+ /;\s*(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER)/i, // Multiple statements
108
+ /UNION\s+(ALL\s+)?SELECT/i, // Union-based injection
109
+ /'\s*(OR|AND)\s*'[^']*'\s*=/i, // Quote-based injection
110
+ /'\s*(OR|AND)\s*\d+\s*=\s*\d+/i, // Numeric injection
111
+ /CONCAT\s*\(\s*0x[0-9a-f]+/i, // Hex concatenation
112
+ /(SLEEP|BENCHMARK)\s*\(/i, // Time-based attacks
113
+ ];
114
+ if (type === DatabaseType.MySQL) {
115
+ suspiciousPatterns.push(/INFORMATION_SCHEMA\.\w+\s+(WHERE|AND|OR)/i);
116
+ }
117
+ for (const pattern of suspiciousPatterns) {
118
+ if (pattern.test(query)) {
119
+ return {
120
+ isValid: false,
121
+ error: 'Query contains suspicious patterns that may indicate SQL injection'
122
+ };
123
+ }
124
+ }
125
+ return { isValid: true };
126
+ }
127
+ static checkSuspiciousPatterns(query) {
128
+ // Check for extremely long queries (potential DoS)
129
+ if (query.length > 10000) {
130
+ return {
131
+ isValid: false,
132
+ error: 'Query is too long. Maximum allowed length is 10,000 characters.'
133
+ };
134
+ }
135
+ // Check for excessive nesting
136
+ const nestedCount = (query.match(/\(/g) || []).length;
137
+ if (nestedCount > 50) {
138
+ return {
139
+ isValid: false,
140
+ error: 'Query has too many nested expressions. Maximum allowed is 50.'
141
+ };
142
+ }
143
+ return { isValid: true };
144
+ }
145
+ static getWarnings(query) {
146
+ const warnings = [];
147
+ // Warn about potentially slow operations
148
+ if (query.includes('SELECT *')) {
149
+ warnings.push('Using SELECT * may return large result sets. Consider specifying specific columns.');
150
+ }
151
+ if (query.includes('ORDER BY') && !query.includes('LIMIT')) {
152
+ warnings.push('ORDER BY without LIMIT may be slow on large tables.');
153
+ }
154
+ if (query.includes('LIKE %') || query.includes("LIKE '%")) {
155
+ warnings.push('Leading wildcard in LIKE patterns may cause slow queries.');
156
+ }
157
+ // Check for cross-joins
158
+ if (query.match(/FROM\s+\w+\s*,\s*\w+/i) && !query.includes('WHERE')) {
159
+ warnings.push('Potential cartesian product detected. Consider adding WHERE conditions.');
160
+ }
161
+ return warnings;
162
+ }
163
+ // Validate table and column names to prevent injection through identifiers
164
+ static validateIdentifier(identifier) {
165
+ if (!identifier || identifier.trim().length === 0) {
166
+ return {
167
+ isValid: false,
168
+ error: 'Identifier cannot be empty'
169
+ };
170
+ }
171
+ // MySQL/PostgreSQL identifier rules (simplified common)
172
+ const validIdentifier = /^[a-zA-Z_][a-zA-Z0-9_$]*$|^`[^`]+`$/;
173
+ if (!validIdentifier.test(identifier.trim())) {
174
+ return {
175
+ isValid: false,
176
+ error: 'Invalid identifier format. Use only letters, numbers, underscore, and dollar sign.'
177
+ };
178
+ }
179
+ // Check length (common limit is 64 characters)
180
+ const cleanIdentifier = identifier.replace(/[`"]/g, '');
181
+ if (cleanIdentifier.length > 64) {
182
+ return {
183
+ isValid: false,
184
+ error: 'Identifier too long. Maximum length is 64 characters.'
185
+ };
186
+ }
187
+ return { isValid: true };
188
+ }
189
+ // Sanitize user input
190
+ static sanitizeInput(input) {
191
+ if (!input)
192
+ return '';
193
+ // Remove null bytes and control characters
194
+ return input
195
+ .replace(/\0/g, '')
196
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')
197
+ .trim();
198
+ }
199
+ // Check if a query is a simple read operation
200
+ static isSimpleReadQuery(query) {
201
+ const normalized = this.normalizeQuery(query);
202
+ const firstWord = normalized.split(' ')[0];
203
+ return ['SELECT', 'SHOW', 'DESCRIBE', 'DESC', 'EXPLAIN', 'WITH', 'VALUES'].includes(firstWord);
204
+ }
205
+ // Estimate query complexity
206
+ static getQueryComplexity(query) {
207
+ const normalized = this.normalizeQuery(query);
208
+ let complexity = 0;
209
+ // Count joins
210
+ complexity += (normalized.match(/\bJOIN\b/g) || []).length * 2;
211
+ // Count subqueries
212
+ complexity += (normalized.match(/\bSELECT\b/g) || []).length - 1;
213
+ // Count aggregation functions
214
+ complexity += (normalized.match(/\b(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\b/g) || []).length;
215
+ // Count sorting and grouping
216
+ if (normalized.includes('ORDER BY'))
217
+ complexity += 1;
218
+ if (normalized.includes('GROUP BY'))
219
+ complexity += 2;
220
+ if (normalized.includes('HAVING'))
221
+ complexity += 1;
222
+ if (complexity <= 2)
223
+ return 'low';
224
+ if (complexity <= 6)
225
+ return 'medium';
226
+ return 'high';
227
+ }
228
+ }
229
+ //# sourceMappingURL=query-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-validator.js","sourceRoot":"","sources":["../../src/validators/query-validator.ts"],"names":[],"mappings":"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"}