@memberjunction/global 6.1.4 → 6.1.6
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/dist/SQLExpressionValidator.d.ts +36 -32
- package/dist/SQLExpressionValidator.d.ts.map +1 -1
- package/dist/SQLExpressionValidator.js +125 -117
- package/dist/SQLExpressionValidator.js.map +1 -1
- package/dist/SQLScreeningScanner.d.ts +91 -0
- package/dist/SQLScreeningScanner.d.ts.map +1 -0
- package/dist/SQLScreeningScanner.js +332 -0
- package/dist/SQLScreeningScanner.js.map +1 -0
- package/dist/__tests__/SQLExpressionValidator.security.test.js +176 -2
- package/dist/__tests__/SQLExpressionValidator.security.test.js.map +1 -1
- package/dist/__tests__/SQLScreeningScanner.test.d.ts +2 -0
- package/dist/__tests__/SQLScreeningScanner.test.d.ts.map +1 -0
- package/dist/__tests__/SQLScreeningScanner.test.js +172 -0
- package/dist/__tests__/SQLScreeningScanner.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @module @memberjunction/global/SQLExpressionValidator
|
|
11
11
|
*/
|
|
12
12
|
import { BaseSingleton } from './BaseSingleton.js';
|
|
13
|
+
import { SQLScreeningDialect } from './SQLScreeningScanner.js';
|
|
13
14
|
/**
|
|
14
15
|
* Dangerous SQL keywords that are never allowed in user-provided expressions
|
|
15
16
|
*/
|
|
@@ -26,34 +27,30 @@ export declare const FULL_QUERY_ALLOWED_KEYWORDS: readonly ["EXISTS", "ANY", "AL
|
|
|
26
27
|
* a schema-enumeration and credential-exfiltration primitive
|
|
27
28
|
* (e.g. `SELECT name, password_hash FROM sys.sql_logins`,
|
|
28
29
|
* `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, `SELECT * FROM pg_catalog.pg_authid`).
|
|
29
|
-
*
|
|
30
|
+
* The check reads {@link SQLScreeningScan.CodeWithIdentifiers}: string literals are removed, so a
|
|
31
|
+
* literal value like `'sys.x'` is safe, and quoted names are unwrapped, so `[sys].[x]` is caught.
|
|
30
32
|
*/
|
|
31
33
|
export declare const BLOCKED_SYSTEM_OBJECT_PATTERNS: RegExp[];
|
|
32
34
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
35
|
+
* Replaces each SQL string literal with one space so that a keyword denylist can be applied to the
|
|
36
|
+
* rest without tripping over keywords inside quoted data (e.g. `Comments LIKE '%--%'`). Quoted
|
|
37
|
+
* identifiers and comments are left as written.
|
|
36
38
|
*
|
|
37
|
-
* 🚨 SECURITY —
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* **backslash escaping** — `/(['"])(?:(?=(\\?))\2[\s\S])*?\1/g`. SQL Server and PostgreSQL do not
|
|
44
|
-
* treat `\` as an escape character, so `x = 'a\') ; DROP TABLE Users; --'` was swallowed whole as
|
|
45
|
-
* one "literal" and stripped to `x = `, which passed every denylist — while the database closed
|
|
46
|
-
* the literal at the real quote and executed the stacked statement.
|
|
47
|
-
*
|
|
48
|
-
* **Do NOT reintroduce backslash-escape handling here, and do NOT inline a second copy of this
|
|
49
|
-
* regex anywhere else — call this function.**
|
|
39
|
+
* 🚨 SECURITY — literals are found by {@link ScanSQLForScreening}, which reads the text the way the
|
|
40
|
+
* database does: a quote inside a T-SQL `[…]` identifier, a comment or a PostgreSQL `$$…$$` string
|
|
41
|
+
* opens no literal, and a backslash escapes a quote only inside a PostgreSQL `E'…'` string. A
|
|
42
|
+
* stripper that removes a span the database does NOT treat as a literal hides everything inside it
|
|
43
|
+
* from the denylist while the database still runs it. Screens should call
|
|
44
|
+
* {@link ScanSQLForScreening} directly, which also reports comments and text it cannot classify.
|
|
50
45
|
*
|
|
51
46
|
* @param sql The clause, expression, or query to strip literals from
|
|
52
|
-
* @
|
|
53
|
-
*
|
|
54
|
-
*
|
|
47
|
+
* @param dialect The dialect that will run the SQL. Without one, the text must read the same way
|
|
48
|
+
* under every dialect the scanner knows.
|
|
49
|
+
* @returns The input with each string literal replaced by a space. The input is returned unchanged
|
|
50
|
+
* when it cannot be classified (for example an unterminated literal) or when the dialects
|
|
51
|
+
* disagree on where its literals are, so a denylist still sees all of it.
|
|
55
52
|
*/
|
|
56
|
-
export declare function StripSQLStringLiterals(sql: string): string;
|
|
53
|
+
export declare function StripSQLStringLiterals(sql: string, dialect?: SQLScreeningDialect): string;
|
|
57
54
|
/**
|
|
58
55
|
* Safe SQL functions allowed in expressions, organized by category
|
|
59
56
|
*/
|
|
@@ -101,6 +98,11 @@ export interface SQLValidationOptions {
|
|
|
101
98
|
additionalAllowed?: string[];
|
|
102
99
|
/** Custom blocked keywords to add */
|
|
103
100
|
additionalBlocked?: string[];
|
|
101
|
+
/**
|
|
102
|
+
* The dialect that will run the SQL, which decides how quotes, identifiers and comments are read.
|
|
103
|
+
* Without one, the SQL must pass under every dialect {@link ScanSQLForScreening} knows.
|
|
104
|
+
*/
|
|
105
|
+
Dialect?: SQLScreeningDialect;
|
|
104
106
|
}
|
|
105
107
|
/**
|
|
106
108
|
* Central SQL expression validator for preventing SQL injection.
|
|
@@ -141,16 +143,20 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
141
143
|
*/
|
|
142
144
|
validate(expression: string, options: SQLValidationOptions): SQLValidationResult;
|
|
143
145
|
/**
|
|
144
|
-
*
|
|
146
|
+
* Runs every check against one dialect's reading of the expression.
|
|
145
147
|
*
|
|
146
|
-
* 🚨 SECURITY:
|
|
147
|
-
*
|
|
148
|
+
* 🚨 SECURITY: the checks read the scanner's projections, never the raw text. Do not add a regex
|
|
149
|
+
* that finds literals, identifiers or comments here; see {@link ScanSQLForScreening}.
|
|
148
150
|
*/
|
|
149
|
-
private
|
|
151
|
+
private validateReading;
|
|
150
152
|
/**
|
|
151
153
|
* Check for dangerous SQL patterns that indicate injection attempts
|
|
152
154
|
*/
|
|
153
155
|
private checkDangerousPatterns;
|
|
156
|
+
/**
|
|
157
|
+
* The keywords {@link checkDangerousPatterns} rejects in this context.
|
|
158
|
+
*/
|
|
159
|
+
private blockedKeywords;
|
|
154
160
|
/**
|
|
155
161
|
* Check that function names are in the allowlist
|
|
156
162
|
*/
|
|
@@ -163,12 +169,6 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
163
169
|
* Validate field references exist in entity (lenient mode - just for logging)
|
|
164
170
|
*/
|
|
165
171
|
private checkFieldReferences;
|
|
166
|
-
/**
|
|
167
|
-
* Strip SQL comments (single-line -- and multi-line block comments) from a query.
|
|
168
|
-
* Used by full_query context to allow agent-generated header comments
|
|
169
|
-
* without triggering the comment injection check.
|
|
170
|
-
*/
|
|
171
|
-
private stripSQLComments;
|
|
172
172
|
/**
|
|
173
173
|
* Escape special regex characters in a string
|
|
174
174
|
*/
|
|
@@ -186,7 +186,11 @@ export declare class SQLExpressionValidator extends BaseSingleton<SQLExpressionV
|
|
|
186
186
|
* Validate a full SQL query (SELECT or WITH/CTE statement).
|
|
187
187
|
* Blocks mutations, dangerous operations, and multi-statement injection.
|
|
188
188
|
* Allows SELECT, subqueries, set operations, and SQL comments.
|
|
189
|
+
*
|
|
190
|
+
* @param sql The query to validate
|
|
191
|
+
* @param dialect The dialect that will run the query. Without one, the query must pass under
|
|
192
|
+
* every dialect {@link ScanSQLForScreening} knows.
|
|
189
193
|
*/
|
|
190
|
-
validateFullQuery(sql: string): SQLValidationResult;
|
|
194
|
+
validateFullQuery(sql: string, dialect?: SQLScreeningDialect): SQLValidationResult;
|
|
191
195
|
}
|
|
192
196
|
//# sourceMappingURL=SQLExpressionValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"SQLExpressionValidator.d.ts","sourceRoot":"","sources":["../src/SQLExpressionValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAGL,mBAAmB,EAGpB,MAAM,uBAAuB,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,sBAAsB,2gBA0CzB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,2BAA2B,wFAe9B,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,EAMlD,CAAC;AAQF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAKzF;AAcD;;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;IAE7B;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,sBAAuB,SAAQ,aAAa,CAAC,sBAAsB,CAAC;IAC/E;;OAEG;;IAKH;;OAEG;IACH,WAAkB,QAAQ,IAAI,sBAAsB,CAEnD;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,mBAAmB;IAmBvF;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA8BvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA0D9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAsBvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;;;;;OAQG;IACI,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB;CAO1F"}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* @module @memberjunction/global/SQLExpressionValidator
|
|
11
11
|
*/
|
|
12
12
|
import { BaseSingleton } from './BaseSingleton.js';
|
|
13
|
+
import { ScanSQLForScreening, SQL_SCREENING_DIALECTS, } from './SQLScreeningScanner.js';
|
|
13
14
|
/**
|
|
14
15
|
* Dangerous SQL keywords that are never allowed in user-provided expressions
|
|
15
16
|
*/
|
|
@@ -67,7 +68,8 @@ export const FULL_QUERY_ALLOWED_KEYWORDS = [
|
|
|
67
68
|
* a schema-enumeration and credential-exfiltration primitive
|
|
68
69
|
* (e.g. `SELECT name, password_hash FROM sys.sql_logins`,
|
|
69
70
|
* `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, `SELECT * FROM pg_catalog.pg_authid`).
|
|
70
|
-
*
|
|
71
|
+
* The check reads {@link SQLScreeningScan.CodeWithIdentifiers}: string literals are removed, so a
|
|
72
|
+
* literal value like `'sys.x'` is safe, and quoted names are unwrapped, so `[sys].[x]` is caught.
|
|
71
73
|
*/
|
|
72
74
|
export const BLOCKED_SYSTEM_OBJECT_PATTERNS = [
|
|
73
75
|
/\bSYS\s*\.\s*\w/i, // SQL Server system catalog schema: sys.sql_logins, sys.objects, sys.fn_*, ...
|
|
@@ -77,42 +79,47 @@ export const BLOCKED_SYSTEM_OBJECT_PATTERNS = [
|
|
|
77
79
|
/\bPG_(AUTHID|SHADOW|USER|ROLES)\b/i, // PostgreSQL credential / role catalogs
|
|
78
80
|
];
|
|
79
81
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* single quote, `''` is an embedded quote, and a backslash is an ORDINARY character that
|
|
83
|
-
* does NOT escape the closing quote. Double-quoted runs are matched with the same doubling
|
|
84
|
-
* rule so a delimited identifier can't hide a payload either.
|
|
85
|
-
*
|
|
86
|
-
* @see StripSQLStringLiterals — use that, not this constant, so every caller gets the
|
|
87
|
-
* documented semantics and the two validators in MJ can never drift apart again.
|
|
82
|
+
* The keywords a full query may open with. Without the `u` flag, the `i` flag matches ASCII letters
|
|
83
|
+
* only, so no other letter is case-mapped to S, E, L, C, T, W, I or H.
|
|
88
84
|
*/
|
|
89
|
-
const
|
|
85
|
+
const FULL_QUERY_OPENING_KEYWORD = /^(?:SELECT|WITH)$/i;
|
|
90
86
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* 🚨 SECURITY — this is the single implementation of literal-stripping for MJ's SQL screens, and
|
|
96
|
-
* it MUST stay byte-for-byte consistent with how the database parses literals. If the stripper
|
|
97
|
-
* removes a span the database does NOT treat as a literal, everything hidden inside that span
|
|
98
|
-
* bypasses the denylist while the database still executes it.
|
|
99
|
-
*
|
|
100
|
-
* An earlier version of this logic (duplicated in two places, which is how it survived) honored
|
|
101
|
-
* **backslash escaping** — `/(['"])(?:(?=(\\?))\2[\s\S])*?\1/g`. SQL Server and PostgreSQL do not
|
|
102
|
-
* treat `\` as an escape character, so `x = 'a\') ; DROP TABLE Users; --'` was swallowed whole as
|
|
103
|
-
* one "literal" and stripped to `x = `, which passed every denylist — while the database closed
|
|
104
|
-
* the literal at the real quote and executed the stacked statement.
|
|
87
|
+
* Replaces each SQL string literal with one space so that a keyword denylist can be applied to the
|
|
88
|
+
* rest without tripping over keywords inside quoted data (e.g. `Comments LIKE '%--%'`). Quoted
|
|
89
|
+
* identifiers and comments are left as written.
|
|
105
90
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
91
|
+
* 🚨 SECURITY — literals are found by {@link ScanSQLForScreening}, which reads the text the way the
|
|
92
|
+
* database does: a quote inside a T-SQL `[…]` identifier, a comment or a PostgreSQL `$$…$$` string
|
|
93
|
+
* opens no literal, and a backslash escapes a quote only inside a PostgreSQL `E'…'` string. A
|
|
94
|
+
* stripper that removes a span the database does NOT treat as a literal hides everything inside it
|
|
95
|
+
* from the denylist while the database still runs it. Screens should call
|
|
96
|
+
* {@link ScanSQLForScreening} directly, which also reports comments and text it cannot classify.
|
|
108
97
|
*
|
|
109
98
|
* @param sql The clause, expression, or query to strip literals from
|
|
110
|
-
* @
|
|
111
|
-
*
|
|
112
|
-
*
|
|
99
|
+
* @param dialect The dialect that will run the SQL. Without one, the text must read the same way
|
|
100
|
+
* under every dialect the scanner knows.
|
|
101
|
+
* @returns The input with each string literal replaced by a space. The input is returned unchanged
|
|
102
|
+
* when it cannot be classified (for example an unterminated literal) or when the dialects
|
|
103
|
+
* disagree on where its literals are, so a denylist still sees all of it.
|
|
113
104
|
*/
|
|
114
|
-
export function StripSQLStringLiterals(sql) {
|
|
115
|
-
|
|
105
|
+
export function StripSQLStringLiterals(sql, dialect) {
|
|
106
|
+
const scans = (dialect ? [dialect] : SQL_SCREENING_DIALECTS).map(d => ScanSQLForScreening(sql, d));
|
|
107
|
+
if (scans.some(scan => !scan.Classified))
|
|
108
|
+
return sql;
|
|
109
|
+
const readings = scans.map(scan => replaceStringSpans(sql, scan.Spans));
|
|
110
|
+
return readings.every(reading => reading === readings[0]) ? readings[0] : sql;
|
|
111
|
+
}
|
|
112
|
+
/** Writes `sql` with each string span replaced by one space. */
|
|
113
|
+
function replaceStringSpans(sql, spans) {
|
|
114
|
+
let result = '';
|
|
115
|
+
let from = 0;
|
|
116
|
+
for (const span of spans) {
|
|
117
|
+
if (span.Kind !== 'string')
|
|
118
|
+
continue;
|
|
119
|
+
result += sql.slice(from, span.Start) + ' ';
|
|
120
|
+
from = span.End;
|
|
121
|
+
}
|
|
122
|
+
return result + sql.slice(from);
|
|
116
123
|
}
|
|
117
124
|
/**
|
|
118
125
|
* Safe SQL functions allowed in expressions, organized by category
|
|
@@ -186,75 +193,65 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
186
193
|
if (!trimmed) {
|
|
187
194
|
return { valid: false, error: 'Expression cannot be empty' };
|
|
188
195
|
}
|
|
189
|
-
//
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
196
|
+
// Read the text the way the database will. When the dialect is unknown, every reading must pass.
|
|
197
|
+
const dialects = options.Dialect ? [options.Dialect] : SQL_SCREENING_DIALECTS;
|
|
198
|
+
for (const dialect of dialects) {
|
|
199
|
+
const result = this.validateReading(ScanSQLForScreening(trimmed, dialect), options);
|
|
200
|
+
if (!result.valid)
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
return { valid: true };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Runs every check against one dialect's reading of the expression.
|
|
207
|
+
*
|
|
208
|
+
* 🚨 SECURITY: the checks read the scanner's projections, never the raw text. Do not add a regex
|
|
209
|
+
* that finds literals, identifiers or comments here; see {@link ScanSQLForScreening}.
|
|
210
|
+
*/
|
|
211
|
+
validateReading(scan, options) {
|
|
212
|
+
if (!scan.Classified) {
|
|
213
|
+
return {
|
|
214
|
+
valid: false,
|
|
215
|
+
error: `SQL could not be read safely as ${scan.Dialect}: ${scan.Error}`,
|
|
216
|
+
trigger: 'unclassified'
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const dangerCheck = this.checkDangerousPatterns(scan, options);
|
|
193
220
|
if (!dangerCheck.valid)
|
|
194
221
|
return dangerCheck;
|
|
195
|
-
//
|
|
196
|
-
//
|
|
222
|
+
// The function allowlist is designed for expression fragments, not full SQL statements.
|
|
223
|
+
// Quoted names are unwrapped, so a quoted function call is checked too.
|
|
197
224
|
if (options.context !== 'full_query') {
|
|
198
|
-
const functionCheck = this.checkFunctionNames(
|
|
225
|
+
const functionCheck = this.checkFunctionNames(scan.CodeWithIdentifiers, options);
|
|
199
226
|
if (!functionCheck.valid)
|
|
200
227
|
return functionCheck;
|
|
201
228
|
}
|
|
202
|
-
|
|
203
|
-
const contextCheck = this.checkContextRules(withoutStrings, options);
|
|
229
|
+
const contextCheck = this.checkContextRules(scan, options);
|
|
204
230
|
if (!contextCheck.valid)
|
|
205
231
|
return contextCheck;
|
|
206
|
-
//
|
|
232
|
+
// Optional field reference validation (lenient - just logs warnings)
|
|
207
233
|
if (options.entityFields?.length) {
|
|
208
|
-
this.checkFieldReferences(
|
|
234
|
+
this.checkFieldReferences(scan.Code, options.entityFields);
|
|
209
235
|
}
|
|
210
236
|
return { valid: true };
|
|
211
237
|
}
|
|
212
|
-
/**
|
|
213
|
-
* Remove string literals to avoid false positives in keyword detection.
|
|
214
|
-
*
|
|
215
|
-
* 🚨 SECURITY: delegates to {@link StripSQLStringLiterals} — read the warning there before
|
|
216
|
-
* changing anything about how literals are matched. This must never grow its own regex again.
|
|
217
|
-
*/
|
|
218
|
-
removeStringLiterals(expression) {
|
|
219
|
-
return StripSQLStringLiterals(expression);
|
|
220
|
-
}
|
|
221
238
|
/**
|
|
222
239
|
* Check for dangerous SQL patterns that indicate injection attempts
|
|
223
240
|
*/
|
|
224
|
-
checkDangerousPatterns(
|
|
241
|
+
checkDangerousPatterns(scan, options) {
|
|
225
242
|
const isFullQuery = options.context === 'full_query';
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
// Add SELECT to blocked unless context allows it (prevents subqueries in expressions)
|
|
237
|
-
if (!isFullQuery && !options.allowSubqueries && !blocked.includes('SELECT')) {
|
|
238
|
-
blocked.push('SELECT');
|
|
239
|
-
}
|
|
240
|
-
// For full_query, strip comments before keyword checking (agent SQL has header comment blocks).
|
|
241
|
-
// For expressions, comments are still rejected outright as injection vectors.
|
|
242
|
-
let textToCheck;
|
|
243
|
-
if (isFullQuery) {
|
|
244
|
-
textToCheck = this.stripSQLComments(expression).toUpperCase();
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
const upper = expression.toUpperCase();
|
|
248
|
-
if (upper.includes('--') || upper.includes('/*') || upper.includes('*/')) {
|
|
249
|
-
return {
|
|
250
|
-
valid: false,
|
|
251
|
-
error: 'Comments are not allowed in SQL expressions',
|
|
252
|
-
trigger: 'comment'
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
textToCheck = upper;
|
|
243
|
+
const textToCheck = scan.Code.toUpperCase();
|
|
244
|
+
// Full queries may carry comments (agent SQL has header comment blocks); the scan has already
|
|
245
|
+
// blanked them. In expressions, comments are rejected outright as injection vectors, and so is
|
|
246
|
+
// a stray `*/`, which is code.
|
|
247
|
+
if (!isFullQuery && (scan.CommentCount > 0 || textToCheck.includes('*/'))) {
|
|
248
|
+
return {
|
|
249
|
+
valid: false,
|
|
250
|
+
error: 'Comments are not allowed in SQL expressions',
|
|
251
|
+
trigger: 'comment'
|
|
252
|
+
};
|
|
256
253
|
}
|
|
257
|
-
for (const keyword of
|
|
254
|
+
for (const keyword of this.blockedKeywords(options)) {
|
|
258
255
|
// Use word boundaries to avoid false positives (e.g., "DESCRIPTION" containing "EXEC")
|
|
259
256
|
const pattern = new RegExp(`\\b${this.escapeRegex(keyword)}\\b`, 'i');
|
|
260
257
|
if (pattern.test(textToCheck)) {
|
|
@@ -269,9 +266,10 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
269
266
|
// Block references to database system catalogs / metadata objects in ALL contexts
|
|
270
267
|
// (including full_query). These live outside MemberJunction's entity-permission model, so
|
|
271
268
|
// permitting them turns a validated SELECT into a schema-enumeration / credential-exfiltration
|
|
272
|
-
// primitive.
|
|
269
|
+
// primitive. Literals are blanked and quoted names unwrapped, so `[sys].[x]` is caught too.
|
|
270
|
+
const namesToCheck = scan.CodeWithIdentifiers.toUpperCase();
|
|
273
271
|
for (const sysPattern of BLOCKED_SYSTEM_OBJECT_PATTERNS) {
|
|
274
|
-
if (sysPattern.test(
|
|
272
|
+
if (sysPattern.test(namesToCheck)) {
|
|
275
273
|
return {
|
|
276
274
|
valid: false,
|
|
277
275
|
error: 'Access to database system catalogs / metadata objects is not allowed',
|
|
@@ -279,13 +277,10 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
279
277
|
};
|
|
280
278
|
}
|
|
281
279
|
}
|
|
282
|
-
// Check statement terminator (prevents multi-statement injection).
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
const textForSemicolonCheck = isFullQuery
|
|
287
|
-
? this.stripSQLComments(expression).replace(/;\s*$/, '') // strip comments then trailing semicolon
|
|
288
|
-
: expression;
|
|
280
|
+
// Check statement terminator (prevents multi-statement injection). Comments are already
|
|
281
|
+
// blanked, so a full query may end with one semicolon even when a comment follows it
|
|
282
|
+
// (`ORDER BY x DESC; -- highest first`). A semicolon anywhere else indicates injection.
|
|
283
|
+
const textForSemicolonCheck = isFullQuery ? textToCheck.replace(/;\s*$/, '') : textToCheck;
|
|
289
284
|
if (textForSemicolonCheck.includes(';')) {
|
|
290
285
|
return {
|
|
291
286
|
valid: false,
|
|
@@ -295,6 +290,27 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
295
290
|
}
|
|
296
291
|
return { valid: true };
|
|
297
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* The keywords {@link checkDangerousPatterns} rejects in this context.
|
|
295
|
+
*/
|
|
296
|
+
blockedKeywords(options) {
|
|
297
|
+
const isFullQuery = options.context === 'full_query';
|
|
298
|
+
// Build blocked list - explicitly typed as string[] for mutability
|
|
299
|
+
let blocked = [...DANGEROUS_SQL_KEYWORDS];
|
|
300
|
+
if (options.additionalBlocked) {
|
|
301
|
+
blocked.push(...options.additionalBlocked);
|
|
302
|
+
}
|
|
303
|
+
// For full_query context, remove keywords that are legitimate in SELECT statements
|
|
304
|
+
if (isFullQuery) {
|
|
305
|
+
const allowedSet = new Set(FULL_QUERY_ALLOWED_KEYWORDS.map(k => k.toUpperCase()));
|
|
306
|
+
blocked = blocked.filter(kw => !allowedSet.has(kw.toUpperCase()));
|
|
307
|
+
}
|
|
308
|
+
// Add SELECT to blocked unless context allows it (prevents subqueries in expressions)
|
|
309
|
+
if (!isFullQuery && !options.allowSubqueries && !blocked.includes('SELECT')) {
|
|
310
|
+
blocked.push('SELECT');
|
|
311
|
+
}
|
|
312
|
+
return blocked;
|
|
313
|
+
}
|
|
298
314
|
/**
|
|
299
315
|
* Check that function names are in the allowlist
|
|
300
316
|
*/
|
|
@@ -324,12 +340,12 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
324
340
|
/**
|
|
325
341
|
* Context-specific validation rules
|
|
326
342
|
*/
|
|
327
|
-
checkContextRules(
|
|
343
|
+
checkContextRules(scan, options) {
|
|
328
344
|
// For aggregate context, require at least one aggregate function (unless explicitly disabled)
|
|
329
345
|
if (options.context === 'aggregate' && options.requireAggregate !== false) {
|
|
330
346
|
const hasAggregate = ALLOWED_SQL_FUNCTIONS.aggregates.some(fn => {
|
|
331
347
|
const pattern = new RegExp(`\\b${fn}\\s*\\(`, 'i');
|
|
332
|
-
return pattern.test(
|
|
348
|
+
return pattern.test(scan.Code);
|
|
333
349
|
});
|
|
334
350
|
if (!hasAggregate) {
|
|
335
351
|
return {
|
|
@@ -339,17 +355,15 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
339
355
|
};
|
|
340
356
|
}
|
|
341
357
|
}
|
|
342
|
-
// For full_query context, the
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
};
|
|
352
|
-
}
|
|
358
|
+
// For full_query context, the first token (after comments) must be the unquoted keyword SELECT or
|
|
359
|
+
// WITH, compared in ASCII. SQL Server runs a batch that opens with any other name, quoted or not,
|
|
360
|
+
// as a procedure call.
|
|
361
|
+
if (options.context === 'full_query' && !FULL_QUERY_OPENING_KEYWORD.test(scan.LeadingWord ?? '')) {
|
|
362
|
+
return {
|
|
363
|
+
valid: false,
|
|
364
|
+
error: 'Ad-hoc query must start with SELECT or WITH',
|
|
365
|
+
suggestion: 'Only SELECT statements and CTEs (WITH ... AS) are allowed'
|
|
366
|
+
};
|
|
353
367
|
}
|
|
354
368
|
return { valid: true };
|
|
355
369
|
}
|
|
@@ -379,16 +393,6 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
379
393
|
// For now, we allow it to pass
|
|
380
394
|
}
|
|
381
395
|
}
|
|
382
|
-
/**
|
|
383
|
-
* Strip SQL comments (single-line -- and multi-line block comments) from a query.
|
|
384
|
-
* Used by full_query context to allow agent-generated header comments
|
|
385
|
-
* without triggering the comment injection check.
|
|
386
|
-
*/
|
|
387
|
-
stripSQLComments(sql) {
|
|
388
|
-
return sql
|
|
389
|
-
.replace(/--[^\n]*/g, '') // Single-line comments
|
|
390
|
-
.replace(/\/\*[\s\S]*?\*\//g, ''); // Block comments
|
|
391
|
-
}
|
|
392
396
|
/**
|
|
393
397
|
* Escape special regex characters in a string
|
|
394
398
|
*/
|
|
@@ -414,13 +418,17 @@ export class SQLExpressionValidator extends BaseSingleton {
|
|
|
414
418
|
* Validate a full SQL query (SELECT or WITH/CTE statement).
|
|
415
419
|
* Blocks mutations, dangerous operations, and multi-statement injection.
|
|
416
420
|
* Allows SELECT, subqueries, set operations, and SQL comments.
|
|
421
|
+
*
|
|
422
|
+
* @param sql The query to validate
|
|
423
|
+
* @param dialect The dialect that will run the query. Without one, the query must pass under
|
|
424
|
+
* every dialect {@link ScanSQLForScreening} knows.
|
|
417
425
|
*/
|
|
418
|
-
validateFullQuery(sql) {
|
|
426
|
+
validateFullQuery(sql, dialect) {
|
|
419
427
|
// Normalize literal escape sequences before validation — agent-generated
|
|
420
428
|
// SQL may arrive with literal \n instead of real newlines, which breaks
|
|
421
429
|
// comment stripping and the "must start with SELECT" check.
|
|
422
430
|
const normalized = this.normalizeSQLWhitespace(sql);
|
|
423
|
-
return this.validate(normalized, { context: 'full_query' });
|
|
431
|
+
return this.validate(normalized, { context: 'full_query', Dialect: dialect });
|
|
424
432
|
}
|
|
425
433
|
}
|
|
426
434
|
//# 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,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dialect-aware SQL scanner for MemberJunction's SQL denylist screens.
|
|
3
|
+
*
|
|
4
|
+
* A denylist screen is only as good as its idea of which text is code. This scanner reads SQL the
|
|
5
|
+
* way SQL Server or PostgreSQL splits it into tokens and marks every string literal, quoted
|
|
6
|
+
* identifier and comment, so a screen checks exactly the text the database runs as code. When it
|
|
7
|
+
* cannot read the text the way the database would, it reports that, so the screen rejects the text
|
|
8
|
+
* instead of guessing.
|
|
9
|
+
*
|
|
10
|
+
* Used by `SQLExpressionValidator` and `DatabaseProviderBase.ValidateUserProvidedSQLClause`.
|
|
11
|
+
*
|
|
12
|
+
* @module @memberjunction/global/SQLScreeningScanner
|
|
13
|
+
*/
|
|
14
|
+
/** SQL dialects whose lexical rules {@link ScanSQLForScreening} knows. */
|
|
15
|
+
export type SQLScreeningDialect = 'sqlserver' | 'postgresql';
|
|
16
|
+
/**
|
|
17
|
+
* Every dialect {@link ScanSQLForScreening} knows. A screen that does not know which database will
|
|
18
|
+
* run the SQL must accept it under each one.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SQL_SCREENING_DIALECTS: readonly SQLScreeningDialect[];
|
|
21
|
+
/** Kinds of text that the database never runs as code. */
|
|
22
|
+
export type SQLScreeningSpanKind = 'string' | 'identifier' | 'comment';
|
|
23
|
+
/** One string literal, quoted identifier or comment found by {@link ScanSQLForScreening}. */
|
|
24
|
+
export interface SQLScreeningSpan {
|
|
25
|
+
Kind: SQLScreeningSpanKind;
|
|
26
|
+
/** Offset of the first character, including a prefix such as `N` or `E`. */
|
|
27
|
+
Start: number;
|
|
28
|
+
/** Offset just past the last character. */
|
|
29
|
+
End: number;
|
|
30
|
+
}
|
|
31
|
+
/** Result of {@link ScanSQLForScreening}. */
|
|
32
|
+
export interface SQLScreeningScan {
|
|
33
|
+
/** The dialect whose rules were applied. */
|
|
34
|
+
Dialect: SQLScreeningDialect;
|
|
35
|
+
/** True when every character was read the way the database reads it. When false, reject the text. */
|
|
36
|
+
Classified: boolean;
|
|
37
|
+
/** Why the text could not be classified; null when {@link Classified} is true. */
|
|
38
|
+
Error: string | null;
|
|
39
|
+
/** The string literals, quoted identifiers and comments found, in order. */
|
|
40
|
+
Spans: SQLScreeningSpan[];
|
|
41
|
+
/** Number of comments found. */
|
|
42
|
+
CommentCount: number;
|
|
43
|
+
/**
|
|
44
|
+
* The input with each string literal, quoted identifier and comment replaced by one space, and a
|
|
45
|
+
* space between a number and a word written against it. Only code remains, split where the
|
|
46
|
+
* database splits it, so `N'x'UNION` reads as ` UNION` and `1UNION` as `1 UNION`. Keyword,
|
|
47
|
+
* statement-separator and comment-marker checks read this. When {@link Classified} is false,
|
|
48
|
+
* the text from the point where the scan stopped is left as written.
|
|
49
|
+
*/
|
|
50
|
+
Code: string;
|
|
51
|
+
/**
|
|
52
|
+
* {@link Code}, except each quoted identifier is written as its bare name between spaces, so
|
|
53
|
+
* `[sys].[objects]` reads as ` sys . objects `. Checks for object and function names read this,
|
|
54
|
+
* so quoting a name does not hide it.
|
|
55
|
+
*/
|
|
56
|
+
CodeWithIdentifiers: string;
|
|
57
|
+
/**
|
|
58
|
+
* The first token that is not whitespace or a comment, when that token is an unquoted word and
|
|
59
|
+
* the character after it is ASCII, so every server ends the word in the same place. Null when a
|
|
60
|
+
* literal, quoted identifier, number or symbol comes first, or there is no token. Checks for the
|
|
61
|
+
* statement's opening keyword read this.
|
|
62
|
+
*/
|
|
63
|
+
LeadingWord: string | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Reads `sql` the way `dialect` splits it into tokens. Returns the string literals, quoted
|
|
67
|
+
* identifiers and comments it contains, and the code that remains.
|
|
68
|
+
*
|
|
69
|
+
* Both dialects: `'…'` and `N'…'` strings, in which `''` is an escaped quote and a backslash is an
|
|
70
|
+
* ordinary character; `"…"` identifiers with `""` escapes; `--` comments to the end of the line; and
|
|
71
|
+
* nested block comments. SQL Server adds `[…]` identifiers with `]]` escapes. PostgreSQL adds `E'…'`
|
|
72
|
+
* strings, in which a backslash escapes the next character, and dollar-quoted strings (`$$…$$`,
|
|
73
|
+
* `$tag$…$tag$`); a `[` is code there.
|
|
74
|
+
*
|
|
75
|
+
* 🚨 Do not add backslash escapes to plain `'…'` strings. Neither server honors them (PostgreSQL is
|
|
76
|
+
* assumed to run with `standard_conforming_strings = on`, its default since 9.1), and a scanner that
|
|
77
|
+
* does reads `x = 'a\') ; DROP TABLE t; --'` as one literal while the database runs the DROP.
|
|
78
|
+
*
|
|
79
|
+
* The scan stops and reports an error, instead of guessing, when:
|
|
80
|
+
* - a string, quoted identifier, dollar-quoted string or block comment is not closed;
|
|
81
|
+
* - the text contains a NUL character;
|
|
82
|
+
* - a `--` comment contains a line break other than `\n` or `\r\n`;
|
|
83
|
+
* - a PostgreSQL `E'…'` string is followed by another quoted segment, which PostgreSQL can join to
|
|
84
|
+
* it and read with backslash escapes;
|
|
85
|
+
* - on SQL Server, a number is followed by `e` and a word character (`1EXEC` splits two ways).
|
|
86
|
+
*
|
|
87
|
+
* @param sql The clause, expression or query to read
|
|
88
|
+
* @param dialect The dialect whose lexical rules apply
|
|
89
|
+
*/
|
|
90
|
+
export declare function ScanSQLForScreening(sql: string, dialect: SQLScreeningDialect): SQLScreeningScan;
|
|
91
|
+
//# sourceMappingURL=SQLScreeningScanner.d.ts.map
|