@memberjunction/global 5.1.0 → 5.3.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 CHANGED
@@ -324,7 +324,9 @@ Supports comparisons (`==`, `!=`, `<`, `>`, `<=`, `>=`), logical operators (`&&`
324
324
 
325
325
  ### SQLExpressionValidator
326
326
 
327
- Validates user-provided SQL expressions against injection attacks. Provides context-aware validation (WHERE clauses, ORDER BY, aggregates, field references) with an allowlist of safe SQL functions.
327
+ Validates user-provided SQL expressions and full queries against injection attacks. Provides context-aware validation (WHERE clauses, ORDER BY, aggregates, field references, full queries) with an allowlist of safe SQL functions.
328
+
329
+ **Expression validation** (WHERE clauses, aggregates, ORDER BY):
328
330
 
329
331
  ```typescript
330
332
  import { SQLExpressionValidator } from '@memberjunction/global';
@@ -342,9 +344,22 @@ const bad = validator.validate("Name = 'test'; 1=1", {
342
344
  context: 'where_clause'
343
345
  });
344
346
  // bad.valid === false
345
- // bad.error === "Semicolons are not allowed in SQL expressions"
346
347
  ```
347
348
 
349
+ **Full query validation** (ad-hoc SELECT/WITH statements):
350
+
351
+ ```typescript
352
+ // Validate a complete SQL query — allows SELECT, JOINs, subqueries, set operations, comments
353
+ const result = validator.validateFullQuery('SELECT TOP 10 * FROM __mj.vwUsers WHERE IsActive = 1');
354
+ // result.valid === true
355
+
356
+ // Mutations and dangerous operations are blocked
357
+ const bad = validator.validateFullQuery("INSERT INTO Users (Name) VALUES ('hacked')");
358
+ // bad.valid === false, bad.trigger === 'INSERT'
359
+ ```
360
+
361
+ The `full_query` context allows keywords that are legitimate in SELECT statements (EXISTS, ANY, ALL, UNION, INTERSECT, EXCEPT, IF) while still blocking all mutations (INSERT, UPDATE, DELETE, DROP, etc.), dangerous operations (EXEC, OPENROWSET, WAITFOR), and multi-statement injection (semicolons).
362
+
348
363
  ### ClassUtils -- Reflection Helpers
349
364
 
350
365
  Functions for introspecting class hierarchies at runtime.
@@ -589,7 +604,8 @@ function RegisterClass(
589
604
  | Method | Returns | Description |
590
605
  |---|---|---|
591
606
  | `Instance` (static) | `SQLExpressionValidator` | Singleton accessor |
592
- | `validate(expression, options)` | `SQLValidationResult` | Validate a SQL expression |
607
+ | `validate(expression, options)` | `SQLValidationResult` | Validate a SQL expression with context-specific rules |
608
+ | `validateFullQuery(sql)` | `SQLValidationResult` | Validate a full SELECT/WITH query (convenience for `validate(sql, { context: 'full_query' })`) |
593
609
 
594
610
  ### WarningManager
595
611
 
@@ -1,8 +1,9 @@
1
1
  /**
2
- * @fileoverview Unified SQL Expression Validation
2
+ * @fileoverview Unified SQL Expression and Query Validation
3
3
  *
4
- * Central utility for validating user-provided SQL expressions against injection attacks.
5
- * Used by RunView, aggregates, smart filters, and any other feature accepting SQL input.
4
+ * Central utility for validating user-provided SQL expressions and full queries
5
+ * against injection attacks. Used by RunView, aggregates, smart filters, ad-hoc
6
+ * query execution, and any other feature accepting SQL input.
6
7
  *
7
8
  * Located in MJGlobal (lowest-level package) so all packages can use it.
8
9
  *
@@ -12,6 +13,11 @@
12
13
  * Dangerous SQL keywords that are never allowed in user-provided expressions
13
14
  */
14
15
  export declare const DANGEROUS_SQL_KEYWORDS: readonly ["DROP", "CREATE", "ALTER", "TRUNCATE", "RENAME", "INSERT", "UPDATE", "DELETE", "MERGE", "REPLACE", "GRANT", "REVOKE", "DENY", "EXEC", "EXECUTE", "CALL", "PROCEDURE", "FUNCTION", "BEGIN", "COMMIT", "ROLLBACK", "SAVEPOINT", "USE", "DATABASE", "SCHEMA", "IF", "WHILE", "LOOP", "FOR", "GOTO", "UNION", "INTERSECT", "EXCEPT", "EXISTS", "ANY", "ALL", "SOME", "BULK", "OPENROWSET", "OPENDATASOURCE", "OPENQUERY", "XP_", "SP_", "DYNAMIC", "PREPARE", "DEALLOCATE", "WAITFOR", "DELAY", "SLEEP", "SHUTDOWN", "RECONFIGURE"];
16
+ /**
17
+ * Keywords from DANGEROUS_SQL_KEYWORDS that are legitimate in full SELECT queries.
18
+ * These are only unblocked when context is 'full_query'.
19
+ */
20
+ export declare const FULL_QUERY_ALLOWED_KEYWORDS: readonly ["EXISTS", "ANY", "ALL", "SOME", "UNION", "INTERSECT", "EXCEPT", "IF"];
15
21
  /**
16
22
  * Safe SQL functions allowed in expressions, organized by category
17
23
  */
@@ -29,7 +35,7 @@ export declare const ALLOWED_SQL_FUNCTIONS: {
29
35
  /**
30
36
  * Validation context - affects what's allowed
31
37
  */
32
- export type SQLValidationContext = 'where_clause' | 'order_by' | 'aggregate' | 'field_reference';
38
+ export type SQLValidationContext = 'where_clause' | 'order_by' | 'aggregate' | 'field_reference' | 'full_query';
33
39
  /**
34
40
  * Validation result with detailed error information
35
41
  */
@@ -117,9 +123,30 @@ export declare class SQLExpressionValidator {
117
123
  * Validate field references exist in entity (lenient mode - just for logging)
118
124
  */
119
125
  private checkFieldReferences;
126
+ /**
127
+ * Strip SQL comments (single-line -- and multi-line block comments) from a query.
128
+ * Used by full_query context to allow agent-generated header comments
129
+ * without triggering the comment injection check.
130
+ */
131
+ private stripSQLComments;
120
132
  /**
121
133
  * Escape special regex characters in a string
122
134
  */
123
135
  private escapeRegex;
136
+ /**
137
+ * Normalize literal escape sequences in SQL strings.
138
+ * Agent-generated SQL sometimes arrives with literal \n, \r, \t sequences
139
+ * (backslash + letter) instead of actual whitespace characters. This happens
140
+ * when JSON is double-escaped or the SQL passes through a transport layer
141
+ * that doesn't interpret escape sequences. Without normalization, comment
142
+ * stripping fails because the regex expects real newlines.
143
+ */
144
+ private normalizeSQLWhitespace;
145
+ /**
146
+ * Validate a full SQL query (SELECT or WITH/CTE statement).
147
+ * Blocks mutations, dangerous operations, and multi-statement injection.
148
+ * Allows SELECT, subqueries, set operations, and SQL comments.
149
+ */
150
+ validateFullQuery(sql: string): SQLValidationResult;
124
151
  }
125
152
  //# sourceMappingURL=SQLExpressionValidator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB,2gBA0CzB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;CA2BxB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,UAAU,GACV,WAAW,GACX,iBAAiB,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,OAAO,EAAE,oBAAoB,CAAC;IAE9B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,wHAAwH;IACxH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAyB;IAEjD,OAAO;IAEP;;OAEG;IACH,WAAkB,QAAQ,IAAI,sBAAsB,CAKnD;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,mBAAmB;IAiCvF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAgD9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,OAAO,CAAC,WAAW;CAGpB"}
1
+ {"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,eAAO,MAAM,sBAAsB,2gBA0CzB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,2BAA2B,iFAS9B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;CA2BxB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC5B,cAAc,GACd,UAAU,GACV,WAAW,GACX,iBAAiB,GACjB,YAAY,CAAC;AAEjB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,OAAO,EAAE,oBAAoB,CAAC;IAE9B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,wHAAwH;IACxH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAyB;IAEjD,OAAO;IAEP;;OAEG;IACH,WAAkB,QAAQ,IAAI,sBAAsB,CAKnD;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,mBAAmB;IAoCvF;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAoE9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;OAIG;IACI,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB;CAO3D"}
@@ -1,8 +1,9 @@
1
1
  /**
2
- * @fileoverview Unified SQL Expression Validation
2
+ * @fileoverview Unified SQL Expression and Query Validation
3
3
  *
4
- * Central utility for validating user-provided SQL expressions against injection attacks.
5
- * Used by RunView, aggregates, smart filters, and any other feature accepting SQL input.
4
+ * Central utility for validating user-provided SQL expressions and full queries
5
+ * against injection attacks. Used by RunView, aggregates, smart filters, ad-hoc
6
+ * query execution, and any other feature accepting SQL input.
6
7
  *
7
8
  * Located in MJGlobal (lowest-level package) so all packages can use it.
8
9
  *
@@ -41,6 +42,18 @@ export const DANGEROUS_SQL_KEYWORDS = [
41
42
  // System operations
42
43
  'SHUTDOWN', 'RECONFIGURE'
43
44
  ];
45
+ /**
46
+ * Keywords from DANGEROUS_SQL_KEYWORDS that are legitimate in full SELECT queries.
47
+ * These are only unblocked when context is 'full_query'.
48
+ */
49
+ export const FULL_QUERY_ALLOWED_KEYWORDS = [
50
+ // Subquery operators — valid in WHERE EXISTS(...), x > ANY(...)
51
+ 'EXISTS', 'ANY', 'ALL', 'SOME',
52
+ // Set operations — valid for UNION/INTERSECT/EXCEPT queries
53
+ 'UNION', 'INTERSECT', 'EXCEPT',
54
+ // IIF() uses IF internally, CASE WHEN patterns are common
55
+ 'IF',
56
+ ];
44
57
  /**
45
58
  * Safe SQL functions allowed in expressions, organized by category
46
59
  */
@@ -117,10 +130,13 @@ export class SQLExpressionValidator {
117
130
  const dangerCheck = this.checkDangerousPatterns(withoutStrings, options);
118
131
  if (!dangerCheck.valid)
119
132
  return dangerCheck;
120
- // Step 3: Validate function names are in allowlist
121
- const functionCheck = this.checkFunctionNames(withoutStrings, options);
122
- if (!functionCheck.valid)
123
- return functionCheck;
133
+ // Step 3: Validate function names are in allowlist (skip for full queries —
134
+ // the function allowlist is designed for expression fragments, not full SQL statements)
135
+ if (options.context !== 'full_query') {
136
+ const functionCheck = this.checkFunctionNames(withoutStrings, options);
137
+ if (!functionCheck.valid)
138
+ return functionCheck;
139
+ }
124
140
  // Step 4: Context-specific validation
125
141
  const contextCheck = this.checkContextRules(withoutStrings, options);
126
142
  if (!contextCheck.valid)
@@ -144,20 +160,42 @@ export class SQLExpressionValidator {
144
160
  * Check for dangerous SQL patterns that indicate injection attempts
145
161
  */
146
162
  checkDangerousPatterns(expression, options) {
147
- const upper = expression.toUpperCase();
163
+ const isFullQuery = options.context === 'full_query';
148
164
  // Build blocked list - explicitly typed as string[] for mutability
149
- const blocked = [...DANGEROUS_SQL_KEYWORDS];
165
+ let blocked = [...DANGEROUS_SQL_KEYWORDS];
150
166
  if (options.additionalBlocked) {
151
167
  blocked.push(...options.additionalBlocked);
152
168
  }
153
- // Add SELECT to blocked unless explicitly allowed (prevents subqueries)
154
- if (!options.allowSubqueries && !blocked.includes('SELECT')) {
169
+ // For full_query context, remove keywords that are legitimate in SELECT statements
170
+ if (isFullQuery) {
171
+ const allowedSet = new Set(FULL_QUERY_ALLOWED_KEYWORDS.map(k => k.toUpperCase()));
172
+ blocked = blocked.filter(kw => !allowedSet.has(kw.toUpperCase()));
173
+ }
174
+ // Add SELECT to blocked unless context allows it (prevents subqueries in expressions)
175
+ if (!isFullQuery && !options.allowSubqueries && !blocked.includes('SELECT')) {
155
176
  blocked.push('SELECT');
156
177
  }
178
+ // For full_query, strip comments before keyword checking (agent SQL has header comment blocks).
179
+ // For expressions, comments are still rejected outright as injection vectors.
180
+ let textToCheck;
181
+ if (isFullQuery) {
182
+ textToCheck = this.stripSQLComments(expression).toUpperCase();
183
+ }
184
+ else {
185
+ const upper = expression.toUpperCase();
186
+ if (upper.includes('--') || upper.includes('/*') || upper.includes('*/')) {
187
+ return {
188
+ valid: false,
189
+ error: 'Comments are not allowed in SQL expressions',
190
+ trigger: 'comment'
191
+ };
192
+ }
193
+ textToCheck = upper;
194
+ }
157
195
  for (const keyword of blocked) {
158
196
  // Use word boundaries to avoid false positives (e.g., "DESCRIPTION" containing "EXEC")
159
197
  const pattern = new RegExp(`\\b${this.escapeRegex(keyword)}\\b`, 'i');
160
- if (pattern.test(upper)) {
198
+ if (pattern.test(textToCheck)) {
161
199
  return {
162
200
  valid: false,
163
201
  error: `Dangerous SQL keyword detected: ${keyword}`,
@@ -166,16 +204,14 @@ export class SQLExpressionValidator {
166
204
  };
167
205
  }
168
206
  }
169
- // Check comment patterns (common injection technique)
170
- if (upper.includes('--') || upper.includes('/*') || upper.includes('*/')) {
171
- return {
172
- valid: false,
173
- error: 'Comments are not allowed in SQL expressions',
174
- trigger: 'comment'
175
- };
176
- }
177
- // Check statement terminator (prevents multi-statement injection)
178
- if (expression.includes(';')) {
207
+ // Check statement terminator (prevents multi-statement injection).
208
+ // For full_query context, strip comments first (a trailing semicolon may be followed by
209
+ // an inline comment like `ORDER BY x DESC; -- highest first`), then strip the trailing
210
+ // semicolon. Only reject if semicolons remain mid-statement, indicating injection.
211
+ const textForSemicolonCheck = isFullQuery
212
+ ? this.stripSQLComments(expression).replace(/;\s*$/, '') // strip comments then trailing semicolon
213
+ : expression;
214
+ if (textForSemicolonCheck.includes(';')) {
179
215
  return {
180
216
  valid: false,
181
217
  error: 'Semicolons are not allowed in SQL expressions',
@@ -228,6 +264,18 @@ export class SQLExpressionValidator {
228
264
  };
229
265
  }
230
266
  }
267
+ // For full_query context, the query must start with SELECT or WITH (CTE)
268
+ if (options.context === 'full_query') {
269
+ const stripped = this.stripSQLComments(expression).trim();
270
+ const upper = stripped.toUpperCase();
271
+ if (!upper.startsWith('SELECT') && !upper.startsWith('WITH')) {
272
+ return {
273
+ valid: false,
274
+ error: 'Ad-hoc query must start with SELECT or WITH',
275
+ suggestion: 'Only SELECT statements and CTEs (WITH ... AS) are allowed'
276
+ };
277
+ }
278
+ }
231
279
  return { valid: true };
232
280
  }
233
281
  /**
@@ -256,11 +304,48 @@ export class SQLExpressionValidator {
256
304
  // For now, we allow it to pass
257
305
  }
258
306
  }
307
+ /**
308
+ * Strip SQL comments (single-line -- and multi-line block comments) from a query.
309
+ * Used by full_query context to allow agent-generated header comments
310
+ * without triggering the comment injection check.
311
+ */
312
+ stripSQLComments(sql) {
313
+ return sql
314
+ .replace(/--[^\n]*/g, '') // Single-line comments
315
+ .replace(/\/\*[\s\S]*?\*\//g, ''); // Block comments
316
+ }
259
317
  /**
260
318
  * Escape special regex characters in a string
261
319
  */
262
320
  escapeRegex(str) {
263
321
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
264
322
  }
323
+ /**
324
+ * Normalize literal escape sequences in SQL strings.
325
+ * Agent-generated SQL sometimes arrives with literal \n, \r, \t sequences
326
+ * (backslash + letter) instead of actual whitespace characters. This happens
327
+ * when JSON is double-escaped or the SQL passes through a transport layer
328
+ * that doesn't interpret escape sequences. Without normalization, comment
329
+ * stripping fails because the regex expects real newlines.
330
+ */
331
+ normalizeSQLWhitespace(sql) {
332
+ return sql
333
+ .replace(/\\r\\n/g, '\n') // Literal \r\n → newline
334
+ .replace(/\\n/g, '\n') // Literal \n → newline
335
+ .replace(/\\r/g, '\r') // Literal \r → carriage return
336
+ .replace(/\\t/g, '\t'); // Literal \t → tab
337
+ }
338
+ /**
339
+ * Validate a full SQL query (SELECT or WITH/CTE statement).
340
+ * Blocks mutations, dangerous operations, and multi-statement injection.
341
+ * Allows SELECT, subqueries, set operations, and SQL comments.
342
+ */
343
+ validateFullQuery(sql) {
344
+ // Normalize literal escape sequences before validation — agent-generated
345
+ // SQL may arrive with literal \n instead of real newlines, which breaks
346
+ // comment stripping and the "must start with SELECT" check.
347
+ const normalized = this.normalizeSQLWhitespace(sql);
348
+ return this.validate(normalized, { context: 'full_query' });
349
+ }
265
350
  }
266
351
  //# sourceMappingURL=SQLExpressionValidator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SQLExpressionValidator.js","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SQLExpressionValidator.js","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SQLExpressionValidator.security.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SQLExpressionValidator.security.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/SQLExpressionValidator.security.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,328 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { SQLExpressionValidator } from '../SQLExpressionValidator.js';
3
+ /**
4
+ * Adversarial security tests for SQLExpressionValidator.
5
+ * These tests simulate real-world SQL injection attempts that an attacker
6
+ * (or a misguided LLM) might produce.
7
+ */
8
+ describe('SQLExpressionValidator - Security', () => {
9
+ let validator;
10
+ beforeEach(() => {
11
+ validator = SQLExpressionValidator.Instance;
12
+ });
13
+ // ---------------------------------------------------------------
14
+ // Classic SQL injection patterns (full_query context)
15
+ // ---------------------------------------------------------------
16
+ describe('SQL injection attempts (full_query)', () => {
17
+ const ctx = { context: 'full_query' };
18
+ it('should block tautology + stacked DROP', () => {
19
+ const r = validator.validateFullQuery("SELECT * FROM Users WHERE 1=1; DROP TABLE Users");
20
+ expect(r.valid).toBe(false);
21
+ // DROP is detected before semicolon in the keyword scan
22
+ expect(r.trigger).toBe('DROP');
23
+ });
24
+ it('should block UNION-based data exfiltration', () => {
25
+ // This is valid in full_query because UNION is allowed—
26
+ // BUT it must still start with SELECT. The attack vector here
27
+ // is actually fine for full_query (UNION is legitimate).
28
+ // The real guard is that only SELECT queries can be submitted.
29
+ const r = validator.validateFullQuery("SELECT 1 UNION SELECT password FROM sys.sql_logins");
30
+ // UNION is allowed in full_query, so this is valid from a syntax perspective.
31
+ // The protection is that ad-hoc queries run on a read-only connection.
32
+ expect(r.valid).toBe(true);
33
+ });
34
+ it('should block stacked DELETE after SELECT', () => {
35
+ const r = validator.validateFullQuery("SELECT 1; DELETE FROM Users");
36
+ expect(r.valid).toBe(false);
37
+ // DELETE is detected before semicolon in the keyword scan
38
+ expect(r.trigger).toBe('DELETE');
39
+ });
40
+ it('should block INSERT disguised after comment', () => {
41
+ const r = validator.validateFullQuery("SELECT 1 -- \nINSERT INTO Users (Name) VALUES ('hacked')");
42
+ // After stripping comments, "INSERT INTO Users..." is detected
43
+ expect(r.valid).toBe(false);
44
+ expect(r.trigger).toBe('INSERT');
45
+ });
46
+ it('should block EXEC sp_executesql', () => {
47
+ const r = validator.validateFullQuery("EXEC sp_executesql N'SELECT 1'");
48
+ expect(r.valid).toBe(false);
49
+ expect(r.trigger).toBe('EXEC');
50
+ });
51
+ it('should block EXECUTE xp_cmdshell', () => {
52
+ const r = validator.validateFullQuery("EXECUTE xp_cmdshell 'dir'");
53
+ expect(r.valid).toBe(false);
54
+ expect(r.trigger).toBe('EXECUTE');
55
+ });
56
+ it('should block WAITFOR DELAY (time-based blind injection)', () => {
57
+ const r = validator.validateFullQuery("SELECT 1 WHERE 1=1 WAITFOR DELAY '00:00:10'");
58
+ expect(r.valid).toBe(false);
59
+ expect(r.trigger).toBe('WAITFOR');
60
+ });
61
+ it('should block xp_cmdshell via keyword detection', () => {
62
+ const r = validator.validateFullQuery("SELECT 1; EXEC xp_cmdshell 'whoami'");
63
+ expect(r.valid).toBe(false);
64
+ // EXEC is detected before semicolon in the keyword scan
65
+ expect(r.trigger).toBe('EXEC');
66
+ });
67
+ it('should block OPENROWSET file access', () => {
68
+ const r = validator.validateFullQuery("SELECT * FROM OPENROWSET('SQLNCLI', 'Server=evil;', 'SELECT 1')");
69
+ expect(r.valid).toBe(false);
70
+ expect(r.trigger).toBe('OPENROWSET');
71
+ });
72
+ it('should block OPENDATASOURCE', () => {
73
+ const r = validator.validateFullQuery("SELECT * FROM OPENDATASOURCE('SQLNCLI', 'Data Source=evil;').db.dbo.Users");
74
+ expect(r.valid).toBe(false);
75
+ expect(r.trigger).toBe('OPENDATASOURCE');
76
+ });
77
+ it('should block BULK INSERT', () => {
78
+ const r = validator.validateFullQuery("BULK INSERT Users FROM '\\\\evil\\share\\data.csv'");
79
+ expect(r.valid).toBe(false);
80
+ // INSERT comes before BULK in the keyword scan order
81
+ expect(r.trigger).toBe('INSERT');
82
+ });
83
+ it('should block CREATE TABLE', () => {
84
+ const r = validator.validateFullQuery("CREATE TABLE Evil (ID INT)");
85
+ expect(r.valid).toBe(false);
86
+ });
87
+ it('should block ALTER TABLE', () => {
88
+ const r = validator.validateFullQuery("ALTER TABLE Users ADD HackedColumn NVARCHAR(100)");
89
+ expect(r.valid).toBe(false);
90
+ expect(r.trigger).toBe('ALTER');
91
+ });
92
+ it('should block GRANT privilege escalation', () => {
93
+ const r = validator.validateFullQuery("GRANT CONTROL ON DATABASE::mydb TO public");
94
+ expect(r.valid).toBe(false);
95
+ expect(r.trigger).toBe('GRANT');
96
+ });
97
+ it('should block REVOKE', () => {
98
+ const r = validator.validateFullQuery("REVOKE SELECT ON Users FROM someuser");
99
+ expect(r.valid).toBe(false);
100
+ expect(r.trigger).toBe('REVOKE');
101
+ });
102
+ it('should block DENY', () => {
103
+ const r = validator.validateFullQuery("DENY SELECT ON Users TO someuser");
104
+ expect(r.valid).toBe(false);
105
+ expect(r.trigger).toBe('DENY');
106
+ });
107
+ it('should block SHUTDOWN', () => {
108
+ const r = validator.validateFullQuery("SHUTDOWN WITH NOWAIT");
109
+ expect(r.valid).toBe(false);
110
+ expect(r.trigger).toBe('SHUTDOWN');
111
+ });
112
+ it('should block RECONFIGURE', () => {
113
+ const r = validator.validateFullQuery("RECONFIGURE WITH OVERRIDE");
114
+ expect(r.valid).toBe(false);
115
+ expect(r.trigger).toBe('RECONFIGURE');
116
+ });
117
+ it('should block statement not starting with SELECT/WITH', () => {
118
+ const r = validator.validateFullQuery("UPDATE Users SET IsAdmin = 1");
119
+ expect(r.valid).toBe(false);
120
+ expect(r.trigger).toBe('UPDATE');
121
+ });
122
+ it('should block MERGE statement', () => {
123
+ const r = validator.validateFullQuery("MERGE INTO Users AS t USING (SELECT 1 AS ID) AS s ON t.ID = s.ID WHEN MATCHED THEN DELETE");
124
+ expect(r.valid).toBe(false);
125
+ // DELETE comes before MERGE in the keyword scan order
126
+ expect(r.trigger).toBe('DELETE');
127
+ });
128
+ it('should block TRUNCATE TABLE', () => {
129
+ const r = validator.validateFullQuery("TRUNCATE TABLE Users");
130
+ expect(r.valid).toBe(false);
131
+ expect(r.trigger).toBe('TRUNCATE');
132
+ });
133
+ });
134
+ // ---------------------------------------------------------------
135
+ // Obfuscation and bypass attempts
136
+ // ---------------------------------------------------------------
137
+ describe('obfuscation and bypass attempts', () => {
138
+ it('should block keyword in mixed case (DrOp)', () => {
139
+ const r = validator.validateFullQuery("DrOp TaBlE Users");
140
+ expect(r.valid).toBe(false);
141
+ });
142
+ it('should block with extra whitespace around dangerous keyword', () => {
143
+ const r = validator.validateFullQuery(" DELETE FROM Users ");
144
+ expect(r.valid).toBe(false);
145
+ expect(r.trigger).toBe('DELETE');
146
+ });
147
+ it('should block multi-statement via semicolon with whitespace', () => {
148
+ const r = validator.validateFullQuery("SELECT 1 ; DROP TABLE Users");
149
+ expect(r.valid).toBe(false);
150
+ // DROP is detected before semicolon in the keyword scan
151
+ expect(r.trigger).toBe('DROP');
152
+ });
153
+ it('should block newline-separated stacked statements', () => {
154
+ const r = validator.validateFullQuery("SELECT 1;\nDROP TABLE Users");
155
+ expect(r.valid).toBe(false);
156
+ // DROP is detected before semicolon in the keyword scan
157
+ expect(r.trigger).toBe('DROP');
158
+ });
159
+ it('should not be fooled by tab characters in keywords', () => {
160
+ const r = validator.validateFullQuery("SELECT 1;\tDELETE FROM Users");
161
+ expect(r.valid).toBe(false);
162
+ // DELETE is detected before semicolon in the keyword scan
163
+ expect(r.trigger).toBe('DELETE');
164
+ });
165
+ });
166
+ // ---------------------------------------------------------------
167
+ // String literal false-positive prevention
168
+ // ---------------------------------------------------------------
169
+ describe('string literal false-positive prevention', () => {
170
+ it('should allow DROP inside a string literal', () => {
171
+ const r = validator.validateFullQuery("SELECT * FROM __mj.vwLogs WHERE Message = 'We need to DROP the old approach'");
172
+ expect(r.valid).toBe(true);
173
+ });
174
+ it('should allow INSERT inside a string literal', () => {
175
+ const r = validator.validateFullQuery("SELECT * FROM __mj.vwAuditLog WHERE Action = 'INSERT completed'");
176
+ expect(r.valid).toBe(true);
177
+ });
178
+ it('should allow DELETE inside a string literal', () => {
179
+ const r = validator.validateFullQuery("SELECT * FROM __mj.vwUsers WHERE Bio LIKE '%DELETE old records%'");
180
+ expect(r.valid).toBe(true);
181
+ });
182
+ it('should allow EXEC inside a string literal', () => {
183
+ const r = validator.validateFullQuery("SELECT * FROM __mj.vwJobs WHERE Description = 'EXEC the plan'");
184
+ expect(r.valid).toBe(true);
185
+ });
186
+ it('should still block REAL DROP outside string context', () => {
187
+ const r = validator.validateFullQuery("SELECT 'safe text' FROM Users; DROP TABLE Users");
188
+ expect(r.valid).toBe(false);
189
+ // DROP is detected before semicolon in the keyword scan
190
+ expect(r.trigger).toBe('DROP');
191
+ });
192
+ });
193
+ // ---------------------------------------------------------------
194
+ // Expression-level injection (where_clause context)
195
+ // ---------------------------------------------------------------
196
+ describe('expression-level injection (where_clause)', () => {
197
+ const ctx = { context: 'where_clause' };
198
+ it('should block subquery without allowSubqueries', () => {
199
+ const r = validator.validate("ID IN (SELECT ID FROM Users WHERE IsAdmin = 1)", ctx);
200
+ expect(r.valid).toBe(false);
201
+ expect(r.trigger).toBe('SELECT');
202
+ });
203
+ it('should block UNION injection in WHERE clause', () => {
204
+ const r = validator.validate("1=1 UNION SELECT password FROM sys.sql_logins", ctx);
205
+ expect(r.valid).toBe(false);
206
+ expect(r.trigger).toBe('UNION');
207
+ });
208
+ it('should block comment injection in WHERE clause', () => {
209
+ const r = validator.validate("Status = 'Active' -- OR 1=1", ctx);
210
+ expect(r.valid).toBe(false);
211
+ expect(r.trigger).toBe('comment');
212
+ });
213
+ it('should block block comment injection in WHERE clause', () => {
214
+ const r = validator.validate("Status = 'Active' /* OR 1=1 */", ctx);
215
+ expect(r.valid).toBe(false);
216
+ expect(r.trigger).toBe('comment');
217
+ });
218
+ it('should block semicolon injection in WHERE clause', () => {
219
+ const r = validator.validate("1=1; DROP TABLE Users --", ctx);
220
+ expect(r.valid).toBe(false);
221
+ // Either semicolon or comment should trigger
222
+ });
223
+ it('should block EXEC in WHERE clause', () => {
224
+ const r = validator.validate("1=1 AND EXEC sp_help", ctx);
225
+ expect(r.valid).toBe(false);
226
+ expect(r.trigger).toBe('EXEC');
227
+ });
228
+ it('should block WAITFOR in WHERE clause', () => {
229
+ const r = validator.validate("1=1 WAITFOR DELAY '00:00:05'", ctx);
230
+ expect(r.valid).toBe(false);
231
+ expect(r.trigger).toBe('WAITFOR');
232
+ });
233
+ it('should block CREATE in WHERE clause', () => {
234
+ const r = validator.validate("1=1 CREATE TABLE Evil (ID INT)", ctx);
235
+ expect(r.valid).toBe(false);
236
+ expect(r.trigger).toBe('CREATE');
237
+ });
238
+ });
239
+ // ---------------------------------------------------------------
240
+ // Edge cases
241
+ // ---------------------------------------------------------------
242
+ describe('edge cases', () => {
243
+ it('should reject empty string', () => {
244
+ const r = validator.validateFullQuery('');
245
+ expect(r.valid).toBe(false);
246
+ });
247
+ it('should reject whitespace-only string', () => {
248
+ const r = validator.validateFullQuery(' \n\t ');
249
+ expect(r.valid).toBe(false);
250
+ });
251
+ it('should handle very long SELECT query', () => {
252
+ // Build a long but valid query
253
+ const conditions = Array.from({ length: 100 }, (_, i) => `Field${i} = ${i}`).join(' AND ');
254
+ const sql = `SELECT * FROM __mj.vwUsers WHERE ${conditions}`;
255
+ const r = validator.validateFullQuery(sql);
256
+ expect(r.valid).toBe(true);
257
+ });
258
+ it('should handle deeply nested subqueries', () => {
259
+ const sql = `
260
+ SELECT * FROM __mj.vwUsers
261
+ WHERE ID IN (
262
+ SELECT UserID FROM __mj.vwUserRoles
263
+ WHERE RoleID IN (
264
+ SELECT RoleID FROM __mj.vwRoles
265
+ WHERE Name IN (
266
+ SELECT RoleName FROM __mj.vwDefaultRoles
267
+ )
268
+ )
269
+ )
270
+ `;
271
+ const r = validator.validateFullQuery(sql);
272
+ expect(r.valid).toBe(true);
273
+ });
274
+ it('should handle query with only comments (no actual SQL)', () => {
275
+ const sql = `
276
+ -- This is just a comment
277
+ /* Another comment */
278
+ `;
279
+ const r = validator.validateFullQuery(sql);
280
+ // After stripping comments, there's no SELECT/WITH
281
+ expect(r.valid).toBe(false);
282
+ });
283
+ it('should handle query with unicode characters in string literals', () => {
284
+ const sql = "SELECT * FROM __mj.vwUsers WHERE Name = N'Ünïcödé Tëst'";
285
+ const r = validator.validateFullQuery(sql);
286
+ expect(r.valid).toBe(true);
287
+ });
288
+ it('should handle query with escaped single quotes', () => {
289
+ const sql = "SELECT * FROM __mj.vwUsers WHERE Name = 'O''Brien'";
290
+ const r = validator.validateFullQuery(sql);
291
+ expect(r.valid).toBe(true);
292
+ });
293
+ it('should handle query with numeric literals', () => {
294
+ const sql = "SELECT * FROM __mj.vwOrders WHERE Total > 1000.50 AND Quantity < 100";
295
+ const r = validator.validateFullQuery(sql);
296
+ expect(r.valid).toBe(true);
297
+ });
298
+ it('should handle query with multiple CTEs', () => {
299
+ const sql = `
300
+ WITH CTE1 AS (SELECT ID FROM __mj.vwUsers),
301
+ CTE2 AS (SELECT UserID FROM __mj.vwUserRoles)
302
+ SELECT * FROM CTE1 INNER JOIN CTE2 ON CTE1.ID = CTE2.UserID
303
+ `;
304
+ const r = validator.validateFullQuery(sql);
305
+ expect(r.valid).toBe(true);
306
+ });
307
+ it('should handle CROSS APPLY and OUTER APPLY', () => {
308
+ const sql = `
309
+ SELECT u.Name, r.RoleName
310
+ FROM __mj.vwUsers u
311
+ CROSS APPLY (SELECT TOP 1 RoleName FROM __mj.vwUserRoles WHERE UserID = u.ID) r
312
+ `;
313
+ const r = validator.validateFullQuery(sql);
314
+ expect(r.valid).toBe(true);
315
+ });
316
+ it('should handle window functions', () => {
317
+ const sql = `
318
+ SELECT Name,
319
+ ROW_NUMBER() OVER (PARTITION BY Department ORDER BY HireDate) AS RowNum,
320
+ RANK() OVER (ORDER BY Salary DESC) AS SalaryRank
321
+ FROM __mj.vwEmployees
322
+ `;
323
+ const r = validator.validateFullQuery(sql);
324
+ expect(r.valid).toBe(true);
325
+ });
326
+ });
327
+ });
328
+ //# sourceMappingURL=SQLExpressionValidator.security.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SQLExpressionValidator.security.test.js","sourceRoot":"","sources":["../../src/__tests__/SQLExpressionValidator.security.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SQLExpressionValidator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SQLExpressionValidator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/SQLExpressionValidator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,350 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { SQLExpressionValidator, DANGEROUS_SQL_KEYWORDS, FULL_QUERY_ALLOWED_KEYWORDS, ALLOWED_SQL_FUNCTIONS, } from '../SQLExpressionValidator.js';
3
+ describe('SQLExpressionValidator', () => {
4
+ let validator;
5
+ beforeEach(() => {
6
+ validator = SQLExpressionValidator.Instance;
7
+ });
8
+ describe('singleton', () => {
9
+ it('should return the same instance', () => {
10
+ const a = SQLExpressionValidator.Instance;
11
+ const b = SQLExpressionValidator.Instance;
12
+ expect(a).toBe(b);
13
+ });
14
+ });
15
+ // ---------------------------------------------------------------
16
+ // full_query context
17
+ // ---------------------------------------------------------------
18
+ describe('full_query context', () => {
19
+ const ctx = { context: 'full_query' };
20
+ describe('valid queries', () => {
21
+ it('should accept a simple SELECT', () => {
22
+ const r = validator.validate('SELECT TOP 10 * FROM Users', ctx);
23
+ expect(r.valid).toBe(true);
24
+ });
25
+ it('should accept SELECT with JOINs, WHERE, GROUP BY, ORDER BY', () => {
26
+ const sql = `
27
+ SELECT a.Name, COUNT(r.ID) AS TotalRuns
28
+ FROM __mj.vwAIAgents a
29
+ INNER JOIN __mj.vwAIAgentRuns r ON r.AgentID = a.ID
30
+ WHERE r.StartedAt >= DATEADD(DAY, -30, GETDATE())
31
+ GROUP BY a.Name
32
+ ORDER BY TotalRuns DESC
33
+ `;
34
+ const r = validator.validate(sql, ctx);
35
+ expect(r.valid).toBe(true);
36
+ });
37
+ it('should accept WITH (CTE) statement', () => {
38
+ const sql = `
39
+ WITH ActiveAgents AS (
40
+ SELECT AgentID, COUNT(*) AS RunCount
41
+ FROM __mj.vwAIAgentRuns
42
+ GROUP BY AgentID
43
+ )
44
+ SELECT a.Name, aa.RunCount
45
+ FROM __mj.vwAIAgents a
46
+ INNER JOIN ActiveAgents aa ON aa.AgentID = a.ID
47
+ `;
48
+ const r = validator.validate(sql, ctx);
49
+ expect(r.valid).toBe(true);
50
+ });
51
+ it('should accept SELECT with EXISTS subquery', () => {
52
+ const sql = `
53
+ SELECT * FROM __mj.vwUsers u
54
+ WHERE EXISTS (SELECT 1 FROM __mj.vwUserRoles ur WHERE ur.UserID = u.ID)
55
+ `;
56
+ const r = validator.validate(sql, ctx);
57
+ expect(r.valid).toBe(true);
58
+ });
59
+ it('should accept UNION queries', () => {
60
+ const sql = `
61
+ SELECT Name, 'Agent' AS Type FROM __mj.vwAIAgents
62
+ UNION ALL
63
+ SELECT Name, 'Model' AS Type FROM __mj.vwAIModels
64
+ `;
65
+ const r = validator.validate(sql, ctx);
66
+ expect(r.valid).toBe(true);
67
+ });
68
+ it('should accept INTERSECT queries', () => {
69
+ const sql = `
70
+ SELECT UserID FROM __mj.vwUserRoles WHERE RoleID = 'abc'
71
+ INTERSECT
72
+ SELECT UserID FROM __mj.vwUserRoles WHERE RoleID = 'def'
73
+ `;
74
+ const r = validator.validate(sql, ctx);
75
+ expect(r.valid).toBe(true);
76
+ });
77
+ it('should accept EXCEPT queries', () => {
78
+ const sql = `
79
+ SELECT UserID FROM __mj.vwUsers
80
+ EXCEPT
81
+ SELECT UserID FROM __mj.vwUserRoles
82
+ `;
83
+ const r = validator.validate(sql, ctx);
84
+ expect(r.valid).toBe(true);
85
+ });
86
+ it('should accept SQL with single-line comments (stripped, not rejected)', () => {
87
+ const sql = `
88
+ -- ============================================================
89
+ -- Member Event Attendance Summary
90
+ -- ============================================================
91
+ SELECT TOP 100 m.FirstName, m.LastName
92
+ FROM __mj.vwMembers m
93
+ `;
94
+ const r = validator.validate(sql, ctx);
95
+ expect(r.valid).toBe(true);
96
+ });
97
+ it('should accept SQL with block comments', () => {
98
+ const sql = `
99
+ /* Agent performance query */
100
+ SELECT a.Name FROM __mj.vwAIAgents a
101
+ `;
102
+ const r = validator.validate(sql, ctx);
103
+ expect(r.valid).toBe(true);
104
+ });
105
+ it('should accept WHERE x > ANY(...)', () => {
106
+ const sql = `
107
+ SELECT * FROM __mj.vwOrders
108
+ WHERE Total > ANY (SELECT AVG(Total) FROM __mj.vwOrders GROUP BY CustomerID)
109
+ `;
110
+ const r = validator.validate(sql, ctx);
111
+ expect(r.valid).toBe(true);
112
+ });
113
+ it('should accept WHERE x = ALL(...)', () => {
114
+ const sql = `
115
+ SELECT * FROM __mj.vwProducts
116
+ WHERE Price >= ALL (SELECT MIN(Price) FROM __mj.vwProducts GROUP BY CategoryID)
117
+ `;
118
+ const r = validator.validate(sql, ctx);
119
+ expect(r.valid).toBe(true);
120
+ });
121
+ it('should accept IIF function (uses IF keyword internally)', () => {
122
+ const sql = `SELECT IIF(Status = 'Active', 1, 0) AS IsActive FROM __mj.vwUsers`;
123
+ const r = validator.validate(sql, ctx);
124
+ expect(r.valid).toBe(true);
125
+ });
126
+ it('should accept queries with NULLIF, COALESCE, ISNULL', () => {
127
+ const sql = `SELECT COALESCE(FirstName, 'Unknown'), ISNULL(LastName, ''), NULLIF(Status, '') FROM __mj.vwUsers`;
128
+ const r = validator.validate(sql, ctx);
129
+ expect(r.valid).toBe(true);
130
+ });
131
+ it('should accept CASE WHEN expressions', () => {
132
+ const sql = `
133
+ SELECT Name,
134
+ CASE WHEN Status = 'Active' THEN 'Yes' ELSE 'No' END AS IsActive
135
+ FROM __mj.vwUsers
136
+ `;
137
+ const r = validator.validate(sql, ctx);
138
+ expect(r.valid).toBe(true);
139
+ });
140
+ });
141
+ describe('rejected queries', () => {
142
+ it('should reject INSERT statement', () => {
143
+ const r = validator.validate("INSERT INTO Users (Name) VALUES ('test')", ctx);
144
+ expect(r.valid).toBe(false);
145
+ expect(r.trigger).toBe('INSERT');
146
+ });
147
+ it('should reject UPDATE statement', () => {
148
+ const r = validator.validate("UPDATE Users SET Name = 'test'", ctx);
149
+ expect(r.valid).toBe(false);
150
+ expect(r.trigger).toBe('UPDATE');
151
+ });
152
+ it('should reject DELETE statement', () => {
153
+ const r = validator.validate('DELETE FROM Users WHERE ID = 1', ctx);
154
+ expect(r.valid).toBe(false);
155
+ expect(r.trigger).toBe('DELETE');
156
+ });
157
+ it('should reject DROP TABLE', () => {
158
+ const r = validator.validate('DROP TABLE Users', ctx);
159
+ expect(r.valid).toBe(false);
160
+ expect(r.trigger).toBe('DROP');
161
+ });
162
+ it('should reject TRUNCATE', () => {
163
+ const r = validator.validate('TRUNCATE TABLE Users', ctx);
164
+ expect(r.valid).toBe(false);
165
+ expect(r.trigger).toBe('TRUNCATE');
166
+ });
167
+ it('should reject EXEC', () => {
168
+ const r = validator.validate('EXEC sp_help', ctx);
169
+ expect(r.valid).toBe(false);
170
+ expect(r.trigger).toBe('EXEC');
171
+ });
172
+ it('should reject EXECUTE', () => {
173
+ const r = validator.validate("EXECUTE sp_executesql N'SELECT 1'", ctx);
174
+ expect(r.valid).toBe(false);
175
+ expect(r.trigger).toBe('EXECUTE');
176
+ });
177
+ it('should reject statements with semicolons', () => {
178
+ const r = validator.validate('SELECT 1; DROP TABLE Users', ctx);
179
+ expect(r.valid).toBe(false);
180
+ // DROP is detected before semicolon in the keyword scan
181
+ expect(r.trigger).toBe('DROP');
182
+ });
183
+ it('should reject query not starting with SELECT or WITH', () => {
184
+ const r = validator.validate('CREATE TABLE Foo (ID INT)', ctx);
185
+ expect(r.valid).toBe(false);
186
+ });
187
+ it('should reject WAITFOR DELAY', () => {
188
+ const r = validator.validate("WAITFOR DELAY '00:00:05'", ctx);
189
+ expect(r.valid).toBe(false);
190
+ expect(r.trigger).toBe('WAITFOR');
191
+ });
192
+ it('should reject OPENROWSET', () => {
193
+ const r = validator.validate("SELECT * FROM OPENROWSET('SQLNCLI', 'Server=hack;')", ctx);
194
+ expect(r.valid).toBe(false);
195
+ expect(r.trigger).toBe('OPENROWSET');
196
+ });
197
+ it('should reject GRANT', () => {
198
+ const r = validator.validate('GRANT SELECT ON Users TO public', ctx);
199
+ expect(r.valid).toBe(false);
200
+ expect(r.trigger).toBe('GRANT');
201
+ });
202
+ it('should reject SHUTDOWN', () => {
203
+ const r = validator.validate('SHUTDOWN', ctx);
204
+ expect(r.valid).toBe(false);
205
+ expect(r.trigger).toBe('SHUTDOWN');
206
+ });
207
+ });
208
+ });
209
+ // ---------------------------------------------------------------
210
+ // validateFullQuery convenience method
211
+ // ---------------------------------------------------------------
212
+ describe('validateFullQuery', () => {
213
+ it('should pass valid SELECT', () => {
214
+ const r = validator.validateFullQuery('SELECT 1 AS One');
215
+ expect(r.valid).toBe(true);
216
+ });
217
+ it('should pass valid CTE', () => {
218
+ const r = validator.validateFullQuery('WITH cte AS (SELECT 1) SELECT * FROM cte');
219
+ expect(r.valid).toBe(true);
220
+ });
221
+ it('should fail on mutation', () => {
222
+ const r = validator.validateFullQuery("DELETE FROM Users");
223
+ expect(r.valid).toBe(false);
224
+ });
225
+ it('should fail on empty string', () => {
226
+ const r = validator.validateFullQuery('');
227
+ expect(r.valid).toBe(false);
228
+ });
229
+ it('should normalize literal \\n sequences and pass SQL with comment header', () => {
230
+ // Agent-generated SQL arrives with literal \n instead of real newlines
231
+ const sql = '-- Header Comment\\nSELECT TOP 10 * FROM Users\\nWHERE Status = \'Active\'';
232
+ const r = validator.validateFullQuery(sql);
233
+ expect(r.valid).toBe(true);
234
+ });
235
+ it('should normalize literal \\r\\n sequences', () => {
236
+ const sql = '-- Header\\r\\nSELECT 1 AS One';
237
+ const r = validator.validateFullQuery(sql);
238
+ expect(r.valid).toBe(true);
239
+ });
240
+ it('should still reject dangerous queries after normalization', () => {
241
+ const sql = '-- Innocent header\\nDELETE FROM Users';
242
+ const r = validator.validateFullQuery(sql);
243
+ expect(r.valid).toBe(false);
244
+ });
245
+ });
246
+ // ---------------------------------------------------------------
247
+ // Existing contexts (where_clause, aggregate, etc.)
248
+ // ---------------------------------------------------------------
249
+ describe('where_clause context', () => {
250
+ it('should accept simple field comparison', () => {
251
+ const r = validator.validate("Status = 'Active'", { context: 'where_clause' });
252
+ expect(r.valid).toBe(true);
253
+ });
254
+ it('should accept LIKE expression', () => {
255
+ const r = validator.validate("Name LIKE '%test%'", { context: 'where_clause' });
256
+ expect(r.valid).toBe(true);
257
+ });
258
+ it('should accept BETWEEN', () => {
259
+ const r = validator.validate("Age BETWEEN 18 AND 65", { context: 'where_clause' });
260
+ expect(r.valid).toBe(true);
261
+ });
262
+ it('should reject SELECT (subquery) by default', () => {
263
+ const r = validator.validate("ID IN (SELECT ID FROM Users)", { context: 'where_clause' });
264
+ expect(r.valid).toBe(false);
265
+ expect(r.trigger).toBe('SELECT');
266
+ });
267
+ it('should allow SELECT when allowSubqueries is true', () => {
268
+ const r = validator.validate("ID IN (SELECT ID FROM Users)", { context: 'where_clause', allowSubqueries: true });
269
+ expect(r.valid).toBe(true);
270
+ });
271
+ it('should reject comments', () => {
272
+ const r = validator.validate("Status = 'Active' -- comment", { context: 'where_clause' });
273
+ expect(r.valid).toBe(false);
274
+ expect(r.trigger).toBe('comment');
275
+ });
276
+ it('should reject semicolons', () => {
277
+ const r = validator.validate("1=1; DROP TABLE Users", { context: 'where_clause' });
278
+ expect(r.valid).toBe(false);
279
+ // DROP is detected before semicolon in the keyword scan
280
+ expect(r.trigger).toBe('DROP');
281
+ });
282
+ });
283
+ describe('aggregate context', () => {
284
+ it('should accept COUNT expression', () => {
285
+ const r = validator.validate('COUNT(ID)', { context: 'aggregate' });
286
+ expect(r.valid).toBe(true);
287
+ });
288
+ it('should accept SUM expression', () => {
289
+ const r = validator.validate('SUM(OrderTotal)', { context: 'aggregate' });
290
+ expect(r.valid).toBe(true);
291
+ });
292
+ it('should reject non-aggregate expression', () => {
293
+ const r = validator.validate('FieldName', { context: 'aggregate' });
294
+ expect(r.valid).toBe(false);
295
+ expect(r.error).toContain('aggregate function');
296
+ });
297
+ it('should allow non-aggregate when requireAggregate is false', () => {
298
+ const r = validator.validate('FieldName', { context: 'aggregate', requireAggregate: false });
299
+ expect(r.valid).toBe(true);
300
+ });
301
+ });
302
+ describe('order_by context', () => {
303
+ it('should accept simple field name', () => {
304
+ const r = validator.validate('Name ASC', { context: 'order_by' });
305
+ expect(r.valid).toBe(true);
306
+ });
307
+ it('should accept DESC ordering', () => {
308
+ const r = validator.validate('CreatedAt DESC', { context: 'order_by' });
309
+ expect(r.valid).toBe(true);
310
+ });
311
+ });
312
+ // ---------------------------------------------------------------
313
+ // String literal handling (false positive prevention)
314
+ // ---------------------------------------------------------------
315
+ describe('string literal handling', () => {
316
+ it('should not flag keywords inside string literals', () => {
317
+ const r = validator.validate("SELECT * FROM __mj.vwUsers WHERE Description = 'This will DROP the ball'", { context: 'full_query' });
318
+ // The word DROP is inside a string literal, so it should be stripped before checking
319
+ expect(r.valid).toBe(true);
320
+ });
321
+ it('should not flag INSERT inside a string literal', () => {
322
+ const r = validator.validate("SELECT * FROM __mj.vwLogs WHERE Message = 'INSERT completed successfully'", { context: 'full_query' });
323
+ expect(r.valid).toBe(true);
324
+ });
325
+ });
326
+ // ---------------------------------------------------------------
327
+ // Constants exports
328
+ // ---------------------------------------------------------------
329
+ describe('exported constants', () => {
330
+ it('DANGEROUS_SQL_KEYWORDS should include key mutation keywords', () => {
331
+ expect(DANGEROUS_SQL_KEYWORDS).toContain('INSERT');
332
+ expect(DANGEROUS_SQL_KEYWORDS).toContain('UPDATE');
333
+ expect(DANGEROUS_SQL_KEYWORDS).toContain('DELETE');
334
+ expect(DANGEROUS_SQL_KEYWORDS).toContain('DROP');
335
+ expect(DANGEROUS_SQL_KEYWORDS).toContain('EXEC');
336
+ });
337
+ it('FULL_QUERY_ALLOWED_KEYWORDS should include set operations', () => {
338
+ expect(FULL_QUERY_ALLOWED_KEYWORDS).toContain('UNION');
339
+ expect(FULL_QUERY_ALLOWED_KEYWORDS).toContain('EXISTS');
340
+ expect(FULL_QUERY_ALLOWED_KEYWORDS).toContain('ANY');
341
+ expect(FULL_QUERY_ALLOWED_KEYWORDS).toContain('ALL');
342
+ });
343
+ it('ALLOWED_SQL_FUNCTIONS should include aggregate functions', () => {
344
+ expect(ALLOWED_SQL_FUNCTIONS.aggregates).toContain('COUNT');
345
+ expect(ALLOWED_SQL_FUNCTIONS.aggregates).toContain('SUM');
346
+ expect(ALLOWED_SQL_FUNCTIONS.aggregates).toContain('AVG');
347
+ });
348
+ });
349
+ });
350
+ //# sourceMappingURL=SQLExpressionValidator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SQLExpressionValidator.test.js","sourceRoot":"","sources":["../../src/__tests__/SQLExpressionValidator.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/global",
3
3
  "type": "module",
4
- "version": "5.1.0",
4
+ "version": "5.3.0",
5
5
  "description": "MemberJunction: Global Object - Needed for ALL other MJ components",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",