@freshguard/freshguard-core 0.13.2 → 0.15.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/CHANGELOG.md +15 -1
- package/README.md +74 -1
- package/SKILL.md +229 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +74 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/connectors/azure-sql.d.ts +121 -0
- package/dist/connectors/azure-sql.d.ts.map +1 -0
- package/dist/connectors/azure-sql.js +489 -0
- package/dist/connectors/azure-sql.js.map +1 -0
- package/dist/connectors/base-connector.d.ts +139 -0
- package/dist/connectors/base-connector.d.ts.map +1 -1
- package/dist/connectors/base-connector.js +160 -3
- package/dist/connectors/base-connector.js.map +1 -1
- package/dist/connectors/bigquery.d.ts +100 -0
- package/dist/connectors/bigquery.d.ts.map +1 -1
- package/dist/connectors/bigquery.js +143 -2
- package/dist/connectors/bigquery.js.map +1 -1
- package/dist/connectors/duckdb.d.ts +96 -0
- package/dist/connectors/duckdb.d.ts.map +1 -1
- package/dist/connectors/duckdb.js +144 -7
- package/dist/connectors/duckdb.js.map +1 -1
- package/dist/connectors/index.d.ts +28 -0
- package/dist/connectors/index.d.ts.map +1 -1
- package/dist/connectors/index.js +28 -0
- package/dist/connectors/index.js.map +1 -1
- package/dist/connectors/mssql.d.ts +119 -0
- package/dist/connectors/mssql.d.ts.map +1 -0
- package/dist/connectors/mssql.js +483 -0
- package/dist/connectors/mssql.js.map +1 -0
- package/dist/connectors/mysql.d.ts +85 -0
- package/dist/connectors/mysql.d.ts.map +1 -1
- package/dist/connectors/mysql.js +118 -3
- package/dist/connectors/mysql.js.map +1 -1
- package/dist/connectors/postgres.d.ts +85 -0
- package/dist/connectors/postgres.d.ts.map +1 -1
- package/dist/connectors/postgres.js +113 -6
- package/dist/connectors/postgres.js.map +1 -1
- package/dist/connectors/redshift.d.ts +90 -0
- package/dist/connectors/redshift.d.ts.map +1 -1
- package/dist/connectors/redshift.js +131 -7
- package/dist/connectors/redshift.js.map +1 -1
- package/dist/connectors/snowflake.d.ts +108 -0
- package/dist/connectors/snowflake.d.ts.map +1 -1
- package/dist/connectors/snowflake.js +137 -3
- package/dist/connectors/snowflake.js.map +1 -1
- package/dist/connectors/synapse.d.ts +123 -0
- package/dist/connectors/synapse.d.ts.map +1 -0
- package/dist/connectors/synapse.js +495 -0
- package/dist/connectors/synapse.js.map +1 -0
- package/dist/db/index.d.ts +25 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +23 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrate.d.ts +23 -0
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +38 -0
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/schema.d.ts +11 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +70 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/errors/debug-factory.d.ts +38 -0
- package/dist/errors/debug-factory.d.ts.map +1 -1
- package/dist/errors/debug-factory.js +40 -0
- package/dist/errors/debug-factory.js.map +1 -1
- package/dist/errors/index.d.ts +59 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +110 -7
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata/duckdb-storage.d.ts +3 -0
- package/dist/metadata/duckdb-storage.d.ts.map +1 -1
- package/dist/metadata/duckdb-storage.js +6 -0
- package/dist/metadata/duckdb-storage.js.map +1 -1
- package/dist/metadata/factory.d.ts +30 -0
- package/dist/metadata/factory.d.ts.map +1 -1
- package/dist/metadata/factory.js +31 -0
- package/dist/metadata/factory.js.map +1 -1
- package/dist/metadata/index.d.ts +26 -0
- package/dist/metadata/index.d.ts.map +1 -1
- package/dist/metadata/index.js +26 -0
- package/dist/metadata/index.js.map +1 -1
- package/dist/metadata/interface.d.ts +33 -0
- package/dist/metadata/interface.d.ts.map +1 -1
- package/dist/metadata/interface.js +3 -0
- package/dist/metadata/interface.js.map +1 -1
- package/dist/metadata/postgresql-storage.d.ts +3 -0
- package/dist/metadata/postgresql-storage.d.ts.map +1 -1
- package/dist/metadata/postgresql-storage.js +12 -2
- package/dist/metadata/postgresql-storage.js.map +1 -1
- package/dist/metadata/schema-config.d.ts +53 -0
- package/dist/metadata/schema-config.d.ts.map +1 -1
- package/dist/metadata/schema-config.js +64 -0
- package/dist/metadata/schema-config.js.map +1 -1
- package/dist/metadata/types.d.ts +3 -0
- package/dist/metadata/types.d.ts.map +1 -1
- package/dist/metadata/types.js +3 -0
- package/dist/metadata/types.js.map +1 -1
- package/dist/monitor/baseline-calculator.d.ts +56 -0
- package/dist/monitor/baseline-calculator.d.ts.map +1 -1
- package/dist/monitor/baseline-calculator.js +72 -0
- package/dist/monitor/baseline-calculator.js.map +1 -1
- package/dist/monitor/baseline-config.d.ts +77 -0
- package/dist/monitor/baseline-config.d.ts.map +1 -1
- package/dist/monitor/baseline-config.js +79 -1
- package/dist/monitor/baseline-config.js.map +1 -1
- package/dist/monitor/freshness.d.ts +40 -0
- package/dist/monitor/freshness.d.ts.map +1 -1
- package/dist/monitor/freshness.js +82 -3
- package/dist/monitor/freshness.js.map +1 -1
- package/dist/monitor/index.d.ts +29 -0
- package/dist/monitor/index.d.ts.map +1 -1
- package/dist/monitor/index.js +29 -0
- package/dist/monitor/index.js.map +1 -1
- package/dist/monitor/schema-baseline.d.ts +45 -0
- package/dist/monitor/schema-baseline.d.ts.map +1 -1
- package/dist/monitor/schema-baseline.js +63 -5
- package/dist/monitor/schema-baseline.js.map +1 -1
- package/dist/monitor/schema-changes.d.ts +45 -0
- package/dist/monitor/schema-changes.d.ts.map +1 -1
- package/dist/monitor/schema-changes.js +85 -0
- package/dist/monitor/schema-changes.js.map +1 -1
- package/dist/monitor/volume.d.ts +43 -0
- package/dist/monitor/volume.d.ts.map +1 -1
- package/dist/monitor/volume.js +89 -0
- package/dist/monitor/volume.js.map +1 -1
- package/dist/observability/logger.d.ts +91 -0
- package/dist/observability/logger.d.ts.map +1 -1
- package/dist/observability/logger.js +108 -0
- package/dist/observability/logger.js.map +1 -1
- package/dist/observability/metrics.d.ts +140 -0
- package/dist/observability/metrics.d.ts.map +1 -1
- package/dist/observability/metrics.js +184 -7
- package/dist/observability/metrics.js.map +1 -1
- package/dist/resilience/circuit-breaker.d.ts +112 -2
- package/dist/resilience/circuit-breaker.d.ts.map +1 -1
- package/dist/resilience/circuit-breaker.js +140 -6
- package/dist/resilience/circuit-breaker.js.map +1 -1
- package/dist/resilience/index.d.ts +9 -0
- package/dist/resilience/index.d.ts.map +1 -1
- package/dist/resilience/index.js +13 -0
- package/dist/resilience/index.js.map +1 -1
- package/dist/resilience/retry-policy.d.ts +105 -0
- package/dist/resilience/retry-policy.d.ts.map +1 -1
- package/dist/resilience/retry-policy.js +158 -7
- package/dist/resilience/retry-policy.js.map +1 -1
- package/dist/resilience/timeout-manager.d.ts +137 -0
- package/dist/resilience/timeout-manager.d.ts.map +1 -1
- package/dist/resilience/timeout-manager.js +151 -4
- package/dist/resilience/timeout-manager.js.map +1 -1
- package/dist/security/query-analyzer.d.ts +124 -0
- package/dist/security/query-analyzer.d.ts.map +1 -1
- package/dist/security/query-analyzer.js +150 -9
- package/dist/security/query-analyzer.js.map +1 -1
- package/dist/security/schema-cache.d.ts +152 -0
- package/dist/security/schema-cache.d.ts.map +1 -1
- package/dist/security/schema-cache.js +144 -12
- package/dist/security/schema-cache.js.map +1 -1
- package/dist/types/connector.d.ts +68 -1
- package/dist/types/connector.d.ts.map +1 -1
- package/dist/types/connector.js +38 -15
- package/dist/types/connector.js.map +1 -1
- package/dist/types/driver-results.d.ts +28 -0
- package/dist/types/driver-results.d.ts.map +1 -1
- package/dist/types/driver-results.js +12 -0
- package/dist/types/driver-results.js.map +1 -1
- package/dist/types.d.ts +113 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -1
- package/dist/validation/index.d.ts +8 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +12 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/runtime-validator.d.ts +98 -0
- package/dist/validation/runtime-validator.d.ts.map +1 -1
- package/dist/validation/runtime-validator.js +114 -1
- package/dist/validation/runtime-validator.js.map +1 -1
- package/dist/validation/sanitizers.d.ts +59 -0
- package/dist/validation/sanitizers.d.ts.map +1 -1
- package/dist/validation/sanitizers.js +104 -20
- package/dist/validation/sanitizers.js.map +1 -1
- package/dist/validation/schemas.d.ts +73 -0
- package/dist/validation/schemas.d.ts.map +1 -1
- package/dist/validation/schemas.js +132 -5
- package/dist/validation/schemas.js.map +1 -1
- package/dist/validators/index.d.ts +54 -0
- package/dist/validators/index.d.ts.map +1 -1
- package/dist/validators/index.js +93 -2
- package/dist/validators/index.js.map +1 -1
- package/package.json +6 -2
|
@@ -1,82 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Complexity Analyzer for FreshGuard Core Phase 2
|
|
3
|
+
*
|
|
4
|
+
* Analyzes SQL queries for complexity and security risks, providing
|
|
5
|
+
* risk scoring and recommendations for safe query execution.
|
|
6
|
+
*
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Query complexity analysis result
|
|
11
|
+
*/
|
|
1
12
|
export interface QueryComplexity {
|
|
13
|
+
/** Whether the query should be allowed to execute */
|
|
2
14
|
allowExecution: boolean;
|
|
15
|
+
/** Risk score from 0 (safe) to 100 (dangerous) */
|
|
3
16
|
riskScore: number;
|
|
17
|
+
/** Complexity score based on query structure */
|
|
4
18
|
complexityScore: number;
|
|
19
|
+
/** Estimated execution cost */
|
|
5
20
|
estimatedCost: number;
|
|
21
|
+
/** Security warnings found */
|
|
6
22
|
securityWarnings: string[];
|
|
23
|
+
/** Performance warnings found */
|
|
7
24
|
performanceWarnings: string[];
|
|
25
|
+
/** Recommendations for optimization */
|
|
8
26
|
recommendations: string[];
|
|
27
|
+
/** Query analysis details */
|
|
9
28
|
details: QueryAnalysisDetails;
|
|
10
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Detailed query analysis breakdown
|
|
32
|
+
*/
|
|
11
33
|
export interface QueryAnalysisDetails {
|
|
34
|
+
/** Query type (SELECT, INSERT, etc.) */
|
|
12
35
|
queryType: string;
|
|
36
|
+
/** Number of tables involved */
|
|
13
37
|
tableCount: number;
|
|
38
|
+
/** Number of joins */
|
|
14
39
|
joinCount: number;
|
|
40
|
+
/** Has subqueries */
|
|
15
41
|
hasSubqueries: boolean;
|
|
42
|
+
/** Has aggregations */
|
|
16
43
|
hasAggregations: boolean;
|
|
44
|
+
/** Has wildcards in SELECT */
|
|
17
45
|
hasWildcards: boolean;
|
|
46
|
+
/** Has LIMIT clause */
|
|
18
47
|
hasLimit: boolean;
|
|
48
|
+
/** LIMIT value if present */
|
|
19
49
|
limitValue?: number;
|
|
50
|
+
/** Has WHERE clause */
|
|
20
51
|
hasWhere: boolean;
|
|
52
|
+
/** Has ORDER BY clause */
|
|
21
53
|
hasOrderBy: boolean;
|
|
54
|
+
/** Has GROUP BY clause */
|
|
22
55
|
hasGroupBy: boolean;
|
|
56
|
+
/** Has HAVING clause */
|
|
23
57
|
hasHaving: boolean;
|
|
58
|
+
/** Estimated result set size */
|
|
24
59
|
estimatedResultSize: number;
|
|
25
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Table metadata for analysis
|
|
63
|
+
*/
|
|
26
64
|
export interface TableMetadata {
|
|
65
|
+
/** Table name */
|
|
27
66
|
name: string;
|
|
67
|
+
/** Estimated row count */
|
|
28
68
|
estimatedRows: number;
|
|
69
|
+
/** Table size in bytes */
|
|
29
70
|
sizeBytes?: number;
|
|
71
|
+
/** Available indexes */
|
|
30
72
|
indexes: IndexInfo[];
|
|
73
|
+
/** Column information */
|
|
31
74
|
columns: ColumnInfo[];
|
|
75
|
+
/** When metadata was last updated */
|
|
32
76
|
lastUpdated: Date;
|
|
33
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Index information
|
|
80
|
+
*/
|
|
34
81
|
export interface IndexInfo {
|
|
82
|
+
/** Index name */
|
|
35
83
|
name: string;
|
|
84
|
+
/** Columns in the index */
|
|
36
85
|
columns: string[];
|
|
86
|
+
/** Whether index is unique */
|
|
37
87
|
unique: boolean;
|
|
88
|
+
/** Index type (btree, hash, etc.) */
|
|
38
89
|
type?: string;
|
|
39
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Column information
|
|
93
|
+
*/
|
|
40
94
|
export interface ColumnInfo {
|
|
95
|
+
/** Column name */
|
|
41
96
|
name: string;
|
|
97
|
+
/** Data type */
|
|
42
98
|
type: string;
|
|
99
|
+
/** Whether column is nullable */
|
|
43
100
|
nullable: boolean;
|
|
101
|
+
/** Whether column is indexed */
|
|
44
102
|
indexed: boolean;
|
|
103
|
+
/** Estimated cardinality */
|
|
45
104
|
cardinality?: number;
|
|
46
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Query analyzer configuration
|
|
108
|
+
*/
|
|
47
109
|
export interface QueryAnalyzerConfig {
|
|
110
|
+
/** Maximum risk score to allow execution (0-100) */
|
|
48
111
|
maxRiskScore: number;
|
|
112
|
+
/** Maximum complexity score to allow (0-100) */
|
|
49
113
|
maxComplexityScore: number;
|
|
114
|
+
/** Maximum estimated cost to allow */
|
|
50
115
|
maxEstimatedCost: number;
|
|
116
|
+
/** Maximum result set size to allow */
|
|
51
117
|
maxResultSetSize: number;
|
|
118
|
+
/** Enable performance analysis */
|
|
52
119
|
enablePerformanceAnalysis: boolean;
|
|
120
|
+
/** Enable security analysis */
|
|
53
121
|
enableSecurityAnalysis: boolean;
|
|
122
|
+
/** Custom risk factors */
|
|
54
123
|
customRiskFactors: RiskFactor[];
|
|
55
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Custom risk factor definition
|
|
127
|
+
*/
|
|
56
128
|
export interface RiskFactor {
|
|
129
|
+
/** Pattern to match */
|
|
57
130
|
pattern: RegExp;
|
|
131
|
+
/** Risk score to add (0-100) */
|
|
58
132
|
riskScore: number;
|
|
133
|
+
/** Description of the risk */
|
|
59
134
|
description: string;
|
|
135
|
+
/** Whether this should block execution */
|
|
60
136
|
blocking: boolean;
|
|
61
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Analyzes SQL queries for complexity and security risks
|
|
140
|
+
*/
|
|
62
141
|
export declare class QueryComplexityAnalyzer {
|
|
63
142
|
private config;
|
|
64
143
|
private readonly riskFactors;
|
|
65
144
|
constructor(config?: Partial<QueryAnalyzerConfig>);
|
|
145
|
+
/**
|
|
146
|
+
* Analyze a SQL query for complexity and security risks
|
|
147
|
+
*/
|
|
66
148
|
analyzeQuery(sql: string, tableMetadata?: TableMetadata[]): QueryComplexity;
|
|
149
|
+
/**
|
|
150
|
+
* Calculate query complexity score (0-100)
|
|
151
|
+
*/
|
|
67
152
|
private calculateComplexityScore;
|
|
153
|
+
/**
|
|
154
|
+
* Calculate security risk score (0-100)
|
|
155
|
+
*/
|
|
68
156
|
private calculateRiskScore;
|
|
157
|
+
/**
|
|
158
|
+
* Calculate estimated execution cost
|
|
159
|
+
*/
|
|
69
160
|
private calculateEstimatedCost;
|
|
161
|
+
/**
|
|
162
|
+
* Generate security warnings
|
|
163
|
+
*/
|
|
70
164
|
private generateSecurityWarnings;
|
|
165
|
+
/**
|
|
166
|
+
* Generate performance warnings
|
|
167
|
+
*/
|
|
71
168
|
private generatePerformanceWarnings;
|
|
169
|
+
/**
|
|
170
|
+
* Generate optimization recommendations
|
|
171
|
+
*/
|
|
72
172
|
private generateRecommendations;
|
|
173
|
+
/**
|
|
174
|
+
* Determine if query execution should be allowed
|
|
175
|
+
*/
|
|
73
176
|
private shouldAllowExecution;
|
|
177
|
+
/**
|
|
178
|
+
* Update configuration
|
|
179
|
+
*/
|
|
74
180
|
updateConfig(config: Partial<QueryAnalyzerConfig>): void;
|
|
181
|
+
/**
|
|
182
|
+
* Add custom risk factor
|
|
183
|
+
*/
|
|
75
184
|
addRiskFactor(factor: RiskFactor): void;
|
|
185
|
+
/**
|
|
186
|
+
* Get current configuration
|
|
187
|
+
*/
|
|
76
188
|
getConfig(): QueryAnalyzerConfig;
|
|
77
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Create a query analyzer with default configuration
|
|
192
|
+
*/
|
|
78
193
|
export declare function createQueryAnalyzer(config?: Partial<QueryAnalyzerConfig>): QueryComplexityAnalyzer;
|
|
194
|
+
/**
|
|
195
|
+
* Create a strict security analyzer
|
|
196
|
+
*/
|
|
79
197
|
export declare function createSecurityAnalyzer(): QueryComplexityAnalyzer;
|
|
198
|
+
/**
|
|
199
|
+
* Create a performance-focused analyzer
|
|
200
|
+
*/
|
|
80
201
|
export declare function createPerformanceAnalyzer(): QueryComplexityAnalyzer;
|
|
202
|
+
/**
|
|
203
|
+
* Default query analyzer instance
|
|
204
|
+
*/
|
|
81
205
|
export declare const defaultQueryAnalyzer: QueryComplexityAnalyzer;
|
|
82
206
|
//# sourceMappingURL=query-analyzer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-analyzer.d.ts","sourceRoot":"","sources":["../../src/security/query-analyzer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query-analyzer.d.ts","sourceRoot":"","sources":["../../src/security/query-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Complexity Analyzer for FreshGuard Core Phase 2
|
|
3
|
+
*
|
|
4
|
+
* Analyzes SQL queries for complexity and security risks, providing
|
|
5
|
+
* risk scoring and recommendations for safe query execution.
|
|
6
|
+
*
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
// ==============================================
|
|
10
|
+
// Default Configuration
|
|
11
|
+
// ==============================================
|
|
12
|
+
/**
|
|
13
|
+
* Default query analyzer configuration
|
|
14
|
+
*/
|
|
1
15
|
const DEFAULT_CONFIG = {
|
|
2
16
|
maxRiskScore: 70,
|
|
3
17
|
maxComplexityScore: 80,
|
|
4
|
-
maxEstimatedCost: 1000000,
|
|
18
|
+
maxEstimatedCost: 1000000, // 1 million cost units
|
|
5
19
|
maxResultSetSize: 10000,
|
|
6
20
|
enablePerformanceAnalysis: true,
|
|
7
21
|
enableSecurityAnalysis: true,
|
|
8
22
|
customRiskFactors: []
|
|
9
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Default risk factors for security analysis
|
|
26
|
+
*/
|
|
10
27
|
const DEFAULT_RISK_FACTORS = [
|
|
11
28
|
{
|
|
12
29
|
pattern: /union\s+all|union\s+select/i,
|
|
@@ -63,12 +80,26 @@ const DEFAULT_RISK_FACTORS = [
|
|
|
63
80
|
blocking: false
|
|
64
81
|
}
|
|
65
82
|
];
|
|
83
|
+
// ==============================================
|
|
84
|
+
// SQL Parser Utilities
|
|
85
|
+
// ==============================================
|
|
86
|
+
/**
|
|
87
|
+
* Simple SQL parser for query analysis
|
|
88
|
+
* Note: This is a simplified parser for basic analysis
|
|
89
|
+
*/
|
|
66
90
|
class SimpleSQLParser {
|
|
91
|
+
/**
|
|
92
|
+
* Parse basic query structure
|
|
93
|
+
*/
|
|
67
94
|
static parseQuery(sql) {
|
|
68
95
|
const normalizedSql = sql.trim().toLowerCase();
|
|
96
|
+
// Determine query type
|
|
69
97
|
const queryType = this.getQueryType(normalizedSql);
|
|
98
|
+
// Count tables (simplified - counts FROM and JOIN clauses)
|
|
70
99
|
const tableCount = this.countTables(normalizedSql);
|
|
100
|
+
// Count joins
|
|
71
101
|
const joinCount = this.countJoins(normalizedSql);
|
|
102
|
+
// Check for various SQL constructs
|
|
72
103
|
const hasSubqueries = /\(\s*select\b/.test(normalizedSql);
|
|
73
104
|
const hasAggregations = /\b(count|sum|avg|max|min|group_concat)\s*\(/.test(normalizedSql);
|
|
74
105
|
const hasWildcards = /select\s+\*\s+from\b/.test(normalizedSql);
|
|
@@ -76,9 +107,11 @@ class SimpleSQLParser {
|
|
|
76
107
|
const hasOrderBy = /\border\s+by\b/.test(normalizedSql);
|
|
77
108
|
const hasGroupBy = /\bgroup\s+by\b/.test(normalizedSql);
|
|
78
109
|
const hasHaving = /\bhaving\b/.test(normalizedSql);
|
|
110
|
+
// Check for LIMIT
|
|
79
111
|
const limitMatch = /\blimit\s+(\d+)/.exec(normalizedSql);
|
|
80
112
|
const hasLimit = !!limitMatch;
|
|
81
113
|
const limitValue = limitMatch?.[1] ? parseInt(limitMatch[1], 10) : undefined;
|
|
114
|
+
// Estimate result set size (simplified)
|
|
82
115
|
const estimatedResultSize = this.estimateResultSize(tableCount, hasWhere, hasLimit, limitValue);
|
|
83
116
|
return {
|
|
84
117
|
queryType,
|
|
@@ -96,6 +129,9 @@ class SimpleSQLParser {
|
|
|
96
129
|
estimatedResultSize
|
|
97
130
|
};
|
|
98
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Get query type from SQL
|
|
134
|
+
*/
|
|
99
135
|
static getQueryType(sql) {
|
|
100
136
|
if (sql.startsWith('select'))
|
|
101
137
|
return 'SELECT';
|
|
@@ -117,26 +153,47 @@ class SimpleSQLParser {
|
|
|
117
153
|
return 'DESCRIBE';
|
|
118
154
|
return 'UNKNOWN';
|
|
119
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Count number of tables in query
|
|
158
|
+
*/
|
|
120
159
|
static countTables(sql) {
|
|
160
|
+
// Count FROM clauses
|
|
121
161
|
const fromMatches = sql.match(/\bfrom\s+[\w.]+/g) ?? [];
|
|
162
|
+
// Count JOIN clauses
|
|
122
163
|
const joinMatches = sql.match(/\bjoin\s+[\w.]+/g) ?? [];
|
|
123
164
|
return fromMatches.length + joinMatches.length;
|
|
124
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Count number of joins
|
|
168
|
+
*/
|
|
125
169
|
static countJoins(sql) {
|
|
126
170
|
const joinMatches = sql.match(/\b(inner\s+join|left\s+join|right\s+join|full\s+join|join)\b/g) ?? [];
|
|
127
171
|
return joinMatches.length;
|
|
128
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Estimate result set size
|
|
175
|
+
*/
|
|
129
176
|
static estimateResultSize(tableCount, hasWhere, hasLimit, limitValue) {
|
|
177
|
+
// If LIMIT is specified, use that as max
|
|
130
178
|
if (hasLimit && limitValue) {
|
|
131
179
|
return Math.min(limitValue, 10000);
|
|
132
180
|
}
|
|
133
|
-
|
|
181
|
+
// Base estimate on table count and filtering
|
|
182
|
+
let estimate = Math.pow(1000, tableCount); // Exponential growth with joins
|
|
183
|
+
// Reduce estimate if WHERE clause exists (assumes filtering)
|
|
134
184
|
if (hasWhere) {
|
|
135
|
-
estimate = Math.floor(estimate * 0.1);
|
|
185
|
+
estimate = Math.floor(estimate * 0.1); // Assume WHERE reduces by 90%
|
|
136
186
|
}
|
|
187
|
+
// Cap at reasonable maximum
|
|
137
188
|
return Math.min(estimate, 100000);
|
|
138
189
|
}
|
|
139
190
|
}
|
|
191
|
+
// ==============================================
|
|
192
|
+
// Query Complexity Analyzer
|
|
193
|
+
// ==============================================
|
|
194
|
+
/**
|
|
195
|
+
* Analyzes SQL queries for complexity and security risks
|
|
196
|
+
*/
|
|
140
197
|
export class QueryComplexityAnalyzer {
|
|
141
198
|
config;
|
|
142
199
|
riskFactors;
|
|
@@ -147,14 +204,21 @@ export class QueryComplexityAnalyzer {
|
|
|
147
204
|
...(config.customRiskFactors ?? [])
|
|
148
205
|
];
|
|
149
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Analyze a SQL query for complexity and security risks
|
|
209
|
+
*/
|
|
150
210
|
analyzeQuery(sql, tableMetadata = []) {
|
|
211
|
+
// Parse query structure
|
|
151
212
|
const details = SimpleSQLParser.parseQuery(sql);
|
|
213
|
+
// Calculate scores
|
|
152
214
|
const complexityScore = this.calculateComplexityScore(details, tableMetadata);
|
|
153
215
|
const riskScore = this.calculateRiskScore(sql, details);
|
|
154
216
|
const estimatedCost = this.calculateEstimatedCost(details, tableMetadata);
|
|
217
|
+
// Generate warnings and recommendations
|
|
155
218
|
const securityWarnings = this.generateSecurityWarnings(sql, details);
|
|
156
219
|
const performanceWarnings = this.generatePerformanceWarnings(details, tableMetadata);
|
|
157
220
|
const recommendations = this.generateRecommendations(details, securityWarnings, performanceWarnings);
|
|
221
|
+
// Determine if execution should be allowed
|
|
158
222
|
const allowExecution = this.shouldAllowExecution(sql, riskScore, complexityScore, estimatedCost, details);
|
|
159
223
|
return {
|
|
160
224
|
allowExecution,
|
|
@@ -167,8 +231,12 @@ export class QueryComplexityAnalyzer {
|
|
|
167
231
|
details
|
|
168
232
|
};
|
|
169
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Calculate query complexity score (0-100)
|
|
236
|
+
*/
|
|
170
237
|
calculateComplexityScore(details, _tableMetadata) {
|
|
171
238
|
let score = 0;
|
|
239
|
+
// Base score by query type
|
|
172
240
|
switch (details.queryType) {
|
|
173
241
|
case 'SELECT':
|
|
174
242
|
score += 5;
|
|
@@ -193,79 +261,107 @@ export class QueryComplexityAnalyzer {
|
|
|
193
261
|
break;
|
|
194
262
|
default: score += 10;
|
|
195
263
|
}
|
|
196
|
-
|
|
197
|
-
score += Math.min(details.
|
|
264
|
+
// Table complexity
|
|
265
|
+
score += Math.min(details.tableCount * 10, 30); // Max 30 for tables
|
|
266
|
+
// Join complexity
|
|
267
|
+
score += Math.min(details.joinCount * 15, 40); // Max 40 for joins
|
|
268
|
+
// Subquery complexity
|
|
198
269
|
if (details.hasSubqueries)
|
|
199
270
|
score += 20;
|
|
271
|
+
// Aggregation complexity
|
|
200
272
|
if (details.hasAggregations)
|
|
201
273
|
score += 10;
|
|
274
|
+
// Wildcard penalty (SELECT *)
|
|
202
275
|
if (details.hasWildcards)
|
|
203
276
|
score += 15;
|
|
277
|
+
// Missing WHERE clause on multi-table queries
|
|
204
278
|
if (details.tableCount > 1 && !details.hasWhere)
|
|
205
279
|
score += 25;
|
|
280
|
+
// Large result set penalty
|
|
206
281
|
if (details.estimatedResultSize > 1000)
|
|
207
282
|
score += 10;
|
|
208
283
|
if (details.estimatedResultSize > 10000)
|
|
209
284
|
score += 20;
|
|
285
|
+
// No LIMIT on potentially large results
|
|
210
286
|
if (!details.hasLimit && details.estimatedResultSize > 1000)
|
|
211
287
|
score += 15;
|
|
212
288
|
return Math.min(score, 100);
|
|
213
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Calculate security risk score (0-100)
|
|
292
|
+
*/
|
|
214
293
|
calculateRiskScore(sql, details) {
|
|
215
294
|
let score = 0;
|
|
216
295
|
if (!this.config.enableSecurityAnalysis) {
|
|
217
296
|
return 0;
|
|
218
297
|
}
|
|
298
|
+
// Check against risk factors
|
|
219
299
|
for (const factor of this.riskFactors) {
|
|
220
300
|
if (factor.pattern.test(sql)) {
|
|
221
301
|
score += factor.riskScore;
|
|
222
302
|
}
|
|
223
303
|
}
|
|
304
|
+
// Additional risk factors based on query structure
|
|
224
305
|
if (details.queryType !== 'SELECT' && details.queryType !== 'SHOW' && details.queryType !== 'DESCRIBE') {
|
|
225
|
-
score += 30;
|
|
306
|
+
score += 30; // Non-read operations are inherently riskier
|
|
226
307
|
}
|
|
308
|
+
// Multiple statements (potential injection)
|
|
227
309
|
const statementCount = sql.split(';').filter(s => s.trim()).length;
|
|
228
310
|
if (statementCount > 1) {
|
|
229
311
|
score += 40;
|
|
230
312
|
}
|
|
231
313
|
return Math.min(score, 100);
|
|
232
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Calculate estimated execution cost
|
|
317
|
+
*/
|
|
233
318
|
calculateEstimatedCost(details, tableMetadata) {
|
|
234
|
-
let cost = 1;
|
|
319
|
+
let cost = 1; // Base cost
|
|
320
|
+
// Cost based on estimated result size
|
|
235
321
|
cost += details.estimatedResultSize * 0.1;
|
|
322
|
+
// Join costs (exponential)
|
|
236
323
|
if (details.joinCount > 0) {
|
|
237
324
|
cost *= Math.pow(10, details.joinCount);
|
|
238
325
|
}
|
|
326
|
+
// Table scan costs
|
|
239
327
|
for (let i = 0; i < details.tableCount; i++) {
|
|
240
328
|
const metadata = tableMetadata[i];
|
|
241
329
|
if (metadata) {
|
|
242
330
|
cost += metadata.estimatedRows * 0.01;
|
|
243
331
|
}
|
|
244
332
|
else {
|
|
245
|
-
cost += 10000;
|
|
333
|
+
cost += 10000; // Unknown table - assume large
|
|
246
334
|
}
|
|
247
335
|
}
|
|
336
|
+
// Subquery costs
|
|
248
337
|
if (details.hasSubqueries) {
|
|
249
338
|
cost *= 5;
|
|
250
339
|
}
|
|
340
|
+
// Aggregation costs
|
|
251
341
|
if (details.hasAggregations) {
|
|
252
342
|
cost *= 2;
|
|
253
343
|
}
|
|
344
|
+
// Sorting costs
|
|
254
345
|
if (details.hasOrderBy && !details.hasLimit) {
|
|
255
346
|
cost *= 3;
|
|
256
347
|
}
|
|
257
348
|
return Math.floor(cost);
|
|
258
349
|
}
|
|
350
|
+
/**
|
|
351
|
+
* Generate security warnings
|
|
352
|
+
*/
|
|
259
353
|
generateSecurityWarnings(sql, details) {
|
|
260
354
|
const warnings = [];
|
|
261
355
|
if (!this.config.enableSecurityAnalysis) {
|
|
262
356
|
return warnings;
|
|
263
357
|
}
|
|
358
|
+
// Check risk factors
|
|
264
359
|
for (const factor of this.riskFactors) {
|
|
265
360
|
if (factor.pattern.test(sql)) {
|
|
266
361
|
warnings.push(factor.description);
|
|
267
362
|
}
|
|
268
363
|
}
|
|
364
|
+
// Additional security checks
|
|
269
365
|
if (details.queryType !== 'SELECT' && details.queryType !== 'SHOW' && details.queryType !== 'DESCRIBE') {
|
|
270
366
|
warnings.push('Non-read operation detected - ensure proper authorization');
|
|
271
367
|
}
|
|
@@ -277,36 +373,49 @@ export class QueryComplexityAnalyzer {
|
|
|
277
373
|
}
|
|
278
374
|
return warnings;
|
|
279
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Generate performance warnings
|
|
378
|
+
*/
|
|
280
379
|
generatePerformanceWarnings(details, tableMetadata) {
|
|
281
380
|
const warnings = [];
|
|
282
381
|
if (!this.config.enablePerformanceAnalysis) {
|
|
283
382
|
return warnings;
|
|
284
383
|
}
|
|
384
|
+
// Large result set without LIMIT
|
|
285
385
|
if (details.estimatedResultSize > 1000 && !details.hasLimit) {
|
|
286
386
|
warnings.push(`Large result set estimated (${details.estimatedResultSize}) without LIMIT clause`);
|
|
287
387
|
}
|
|
388
|
+
// Multiple joins without WHERE
|
|
288
389
|
if (details.joinCount > 1 && !details.hasWhere) {
|
|
289
390
|
warnings.push('Multiple JOINs without WHERE clause may produce Cartesian product');
|
|
290
391
|
}
|
|
392
|
+
// SELECT * on large tables
|
|
291
393
|
if (details.hasWildcards && tableMetadata.some(t => t.estimatedRows > 10000)) {
|
|
292
394
|
warnings.push('SELECT * on large table(s) - consider selecting specific columns');
|
|
293
395
|
}
|
|
396
|
+
// ORDER BY without LIMIT on large result
|
|
294
397
|
if (details.hasOrderBy && !details.hasLimit && details.estimatedResultSize > 1000) {
|
|
295
398
|
warnings.push('ORDER BY without LIMIT on large result set - consider adding LIMIT');
|
|
296
399
|
}
|
|
400
|
+
// Subqueries
|
|
297
401
|
if (details.hasSubqueries) {
|
|
298
402
|
warnings.push('Subqueries detected - consider using JOINs for better performance');
|
|
299
403
|
}
|
|
300
404
|
return warnings;
|
|
301
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Generate optimization recommendations
|
|
408
|
+
*/
|
|
302
409
|
generateRecommendations(details, securityWarnings, performanceWarnings) {
|
|
303
410
|
const recommendations = [];
|
|
411
|
+
// Security recommendations
|
|
304
412
|
if (securityWarnings.length > 0) {
|
|
305
413
|
recommendations.push('Review security warnings and validate query source');
|
|
306
414
|
}
|
|
307
415
|
if (details.hasWildcards) {
|
|
308
416
|
recommendations.push('Replace SELECT * with specific column names');
|
|
309
417
|
}
|
|
418
|
+
// Performance recommendations
|
|
310
419
|
if (!details.hasLimit && details.estimatedResultSize > 1000) {
|
|
311
420
|
recommendations.push('Add LIMIT clause to prevent large result sets');
|
|
312
421
|
}
|
|
@@ -324,7 +433,11 @@ export class QueryComplexityAnalyzer {
|
|
|
324
433
|
}
|
|
325
434
|
return recommendations;
|
|
326
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Determine if query execution should be allowed
|
|
438
|
+
*/
|
|
327
439
|
shouldAllowExecution(sql, riskScore, complexityScore, estimatedCost, details) {
|
|
440
|
+
// Check against thresholds
|
|
328
441
|
if (riskScore > this.config.maxRiskScore) {
|
|
329
442
|
return false;
|
|
330
443
|
}
|
|
@@ -337,6 +450,7 @@ export class QueryComplexityAnalyzer {
|
|
|
337
450
|
if (details.estimatedResultSize > this.config.maxResultSetSize) {
|
|
338
451
|
return false;
|
|
339
452
|
}
|
|
453
|
+
// Check for blocking risk factors
|
|
340
454
|
for (const factor of this.riskFactors) {
|
|
341
455
|
if (factor.blocking && factor.pattern.test(sql)) {
|
|
342
456
|
return false;
|
|
@@ -344,19 +458,37 @@ export class QueryComplexityAnalyzer {
|
|
|
344
458
|
}
|
|
345
459
|
return true;
|
|
346
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* Update configuration
|
|
463
|
+
*/
|
|
347
464
|
updateConfig(config) {
|
|
348
465
|
this.config = { ...this.config, ...config };
|
|
349
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* Add custom risk factor
|
|
469
|
+
*/
|
|
350
470
|
addRiskFactor(factor) {
|
|
351
471
|
this.riskFactors.push(factor);
|
|
352
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* Get current configuration
|
|
475
|
+
*/
|
|
353
476
|
getConfig() {
|
|
354
477
|
return { ...this.config };
|
|
355
478
|
}
|
|
356
479
|
}
|
|
480
|
+
// ==============================================
|
|
481
|
+
// Factory Functions
|
|
482
|
+
// ==============================================
|
|
483
|
+
/**
|
|
484
|
+
* Create a query analyzer with default configuration
|
|
485
|
+
*/
|
|
357
486
|
export function createQueryAnalyzer(config) {
|
|
358
487
|
return new QueryComplexityAnalyzer(config);
|
|
359
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* Create a strict security analyzer
|
|
491
|
+
*/
|
|
360
492
|
export function createSecurityAnalyzer() {
|
|
361
493
|
return new QueryComplexityAnalyzer({
|
|
362
494
|
maxRiskScore: 30,
|
|
@@ -367,9 +499,12 @@ export function createSecurityAnalyzer() {
|
|
|
367
499
|
enablePerformanceAnalysis: false
|
|
368
500
|
});
|
|
369
501
|
}
|
|
502
|
+
/**
|
|
503
|
+
* Create a performance-focused analyzer
|
|
504
|
+
*/
|
|
370
505
|
export function createPerformanceAnalyzer() {
|
|
371
506
|
return new QueryComplexityAnalyzer({
|
|
372
|
-
maxRiskScore: 100,
|
|
507
|
+
maxRiskScore: 100, // Allow all from security perspective
|
|
373
508
|
maxComplexityScore: 60,
|
|
374
509
|
maxEstimatedCost: 500000,
|
|
375
510
|
maxResultSetSize: 5000,
|
|
@@ -377,5 +512,11 @@ export function createPerformanceAnalyzer() {
|
|
|
377
512
|
enablePerformanceAnalysis: true
|
|
378
513
|
});
|
|
379
514
|
}
|
|
515
|
+
// ==============================================
|
|
516
|
+
// Default Analyzer Instance
|
|
517
|
+
// ==============================================
|
|
518
|
+
/**
|
|
519
|
+
* Default query analyzer instance
|
|
520
|
+
*/
|
|
380
521
|
export const defaultQueryAnalyzer = createQueryAnalyzer();
|
|
381
522
|
//# sourceMappingURL=query-analyzer.js.map
|