@angular-helpers/security 21.0.1 → 21.0.3

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.es.md ADDED
@@ -0,0 +1,119 @@
1
+ [Read in English](./README.md)
2
+
3
+ 🌐 **Documentación y Demo**: https://gaspar1992.github.io/angular-helpers/
4
+
5
+ # Angular Security Helpers
6
+
7
+ Paquete de seguridad para aplicaciones Angular que previene ataques comunes como ReDoS (Regular Expression Denial of Service) usando Web Workers para ejecución segura.
8
+
9
+ ## 🛡️ Características
10
+
11
+ ### **Prevención de ReDoS**
12
+
13
+ - **Ejecución en Web Worker**: Las expresiones regulares se ejecutan en un hilo separado.
14
+ - **Timeout Configurable**: Previene ejecuciones infinitas.
15
+ - **Análisis de Complejidad**: Detecta patrones peligrosos antes de la ejecución.
16
+ - **Modo Seguro**: Solo permite patrones verificados como seguros.
17
+
18
+ ### **Patrón Builder**
19
+
20
+ - **API Fluida**: Construye expresiones regulares de forma intuitiva.
21
+ - **Encadenamiento de Métodos**: `.pattern().group().quantifier()`
22
+ - **Validación en Tiempo Real**: Análisis de seguridad durante la construcción.
23
+
24
+ ## 📦 Instalación
25
+
26
+ ```bash
27
+ npm install @angular-helpers/security
28
+ ```
29
+
30
+ ## 🚀 Uso Básico
31
+
32
+ ### **Configuración**
33
+
34
+ ```typescript
35
+ import { provideSecurity } from '@angular-helpers/security';
36
+
37
+ bootstrapApplication(AppComponent, {
38
+ providers: [
39
+ provideSecurity({
40
+ enableRegexSecurity: true,
41
+ defaultTimeout: 5000,
42
+ safeMode: false,
43
+ }),
44
+ ],
45
+ });
46
+ ```
47
+
48
+ ### **Inyección de Servicios**
49
+
50
+ ```typescript
51
+ import { RegexSecurityService } from '@angular-helpers/security';
52
+
53
+ export class MyComponent {
54
+ private securityService = inject(RegexSecurityService);
55
+
56
+ async validateInput() {
57
+ const pattern = '(.+)+'; // Patrón potencialmente peligroso
58
+ const text = 'texto de prueba';
59
+
60
+ try {
61
+ const result = await this.securityService.testRegex(pattern, text, {
62
+ timeout: 5000,
63
+ safeMode: true,
64
+ });
65
+
66
+ console.log('Coincidencia:', result.match);
67
+ console.log('Tiempo de ejecución:', result.executionTime);
68
+ } catch (error) {
69
+ console.error('Error de validación:', error);
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### **Uso del Builder**
76
+
77
+ ```typescript
78
+ import { RegexSecurityService } from '@angular-helpers/security';
79
+
80
+ const { pattern, security } = RegexSecurityService.builder()
81
+ .startOfLine()
82
+ .characterSet('0-9')
83
+ .quantifier('+')
84
+ .endOfLine()
85
+ .timeout(3000)
86
+ .safeMode()
87
+ .build();
88
+
89
+ // Ejecutar usando el servicio
90
+ const result = await RegexSecurityService.builder()
91
+ .pattern('\\d+')
92
+ .timeout(3000)
93
+ .execute('12345', this.securityService);
94
+ ```
95
+
96
+ ## 📊 Niveles de Riesgo
97
+
98
+ | Nivel | Descripción | Acción |
99
+ | -------------- | -------------------- | ---------------------------------------- |
100
+ | 🟢 **Bajo** | Patrones seguros | Ejecución normal |
101
+ | 🟡 **Medio** | Posible riesgo | Advertencia + timeout |
102
+ | 🟠 **Alto** | Riesgo significativo | Timeout estricto + safe mode recomendado |
103
+ | 🔴 **Crítico** | Patrones peligrosos | Bloqueo por defecto |
104
+
105
+ ## 🔧 Configuración Avanzada
106
+
107
+ ```typescript
108
+ provideSecurity({
109
+ enableRegexSecurity: true,
110
+ defaultTimeout: 5000,
111
+ safeMode: false,
112
+ maxComplexity: 1000,
113
+ allowCatastrophicPatterns: false,
114
+ });
115
+ ```
116
+
117
+ ## 📄 Licencia
118
+
119
+ MIT
package/README.md CHANGED
@@ -1,4 +1,6 @@
1
- [English](README.en.md) | [Español](README.md)
1
+ [Leer en Español](./README.es.md)
2
+
3
+ 🌐 **Documentation & Demo**: https://gaspar1992.github.io/angular-helpers/
2
4
 
3
5
  # Angular Security Helpers
4
6
 
@@ -7,12 +9,14 @@ Security package for Angular applications that prevents common attacks like ReDo
7
9
  ## 🛡️ Features
8
10
 
9
11
  ### **ReDoS Prevention**
12
+
10
13
  - **Web Worker Execution**: Regular expressions are executed in a separate thread.
11
14
  - **Configurable Timeout**: Prevents infinite executions.
12
15
  - **Complexity Analysis**: Detects dangerous patterns before execution.
13
16
  - **Safe Mode**: Only allows patterns verified as safe.
14
17
 
15
18
  ### **Builder Pattern**
19
+
16
20
  - **Fluent API**: Intuitively build regular expressions.
17
21
  - **Method Chaining**: `.pattern().group().quantifier()`
18
22
  - **Real-time Validation**: Security analysis during construction.
@@ -35,20 +39,20 @@ bootstrapApplication(AppComponent, {
35
39
  provideSecurity({
36
40
  enableRegexSecurity: true,
37
41
  defaultTimeout: 5000,
38
- safeMode: false
39
- })
40
- ]
42
+ safeMode: false,
43
+ }),
44
+ ],
41
45
  });
42
46
  ```
43
47
 
44
48
  ### **Service Injection**
45
49
 
46
50
  ```typescript
47
- import { RegexSecurityService } from '@angular-helpers/security';
51
+ import { RegexSecurityService, inject } from '@angular-helpers/security';
48
52
 
49
53
  @Component({...})
50
54
  export class MyComponent {
51
- constructor(private regexSecurity: RegexSecurityService) {}
55
+ private regexSecurity = inject(RegexSecurityService);
52
56
  }
53
57
  ```
54
58
 
@@ -63,7 +67,7 @@ async testEmail(email: string): Promise<boolean> {
63
67
  email,
64
68
  { timeout: 3000 }
65
69
  );
66
-
70
+
67
71
  return result.match;
68
72
  }
69
73
  ```
@@ -71,11 +75,10 @@ async testEmail(email: string): Promise<boolean> {
71
75
  ### **2. Builder Pattern**
72
76
 
73
77
  ```typescript
74
- import { RegexSecurityBuilder } from '@angular-helpers/security';
78
+ import { RegexSecurityService } from '@angular-helpers/security';
75
79
 
76
80
  // Fluent regular expression construction
77
- const emailRegex = RegexSecurityBuilder
78
- .builder()
81
+ const { pattern, security } = RegexSecurityService.builder()
79
82
  .startOfLine()
80
83
  .characterSet('a-zA-Z0-9._%+-')
81
84
  .quantifier('+')
@@ -91,8 +94,7 @@ const emailRegex = RegexSecurityBuilder
91
94
  .build();
92
95
 
93
96
  // Direct execution
94
- const result = await RegexSecurityBuilder
95
- .builder()
97
+ const result = await RegexSecurityService.builder()
96
98
  .pattern('^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$')
97
99
  .timeout(3000)
98
100
  .execute(email, this.regexSecurity);
@@ -103,16 +105,16 @@ const result = await RegexSecurityBuilder
103
105
  ```typescript
104
106
  async analyzePattern(pattern: string): Promise<void> {
105
107
  const analysis = await this.regexSecurity.analyzePatternSecurity(pattern);
106
-
108
+
107
109
  if (!analysis.safe) {
108
110
  console.warn('⚠️ Pattern not safe:', analysis.warnings);
109
111
  console.info('💡 Recommendations:', analysis.recommendations);
110
-
112
+
111
113
  if (analysis.risk === 'critical') {
112
114
  throw new Error('Pattern rejected due to critical security risk');
113
115
  }
114
116
  }
115
-
117
+
116
118
  console.log(`✅ Pattern complexity: ${analysis.complexity}`);
117
119
  console.log(`🎯 Risk level: ${analysis.risk}`);
118
120
  }
@@ -124,29 +126,29 @@ async analyzePattern(pattern: string): Promise<void> {
124
126
  @Component({...})
125
127
  export class FormValidationComponent {
126
128
  constructor(private regexSecurity: RegexSecurityService) {}
127
-
129
+
128
130
  async validateUsername(username: string): Promise<boolean> {
129
131
  const result = await this.regexSecurity.testRegex(
130
132
  '^[a-zA-Z0-9_]{3,20}$',
131
133
  username,
132
134
  { timeout: 1000, safeMode: true }
133
135
  );
134
-
136
+
135
137
  if (result.timeout) {
136
138
  throw new Error('Username validation timeout - possible ReDoS attack');
137
139
  }
138
-
140
+
139
141
  if (result.error) {
140
142
  console.error('Validation error:', result.error);
141
143
  return false;
142
144
  }
143
-
145
+
144
146
  return result.match;
145
147
  }
146
-
148
+
147
149
  async validateComplexInput(input: string): Promise<boolean> {
148
150
  // Builder pattern for complex validation
149
- const result = await RegexSecurityBuilder
151
+ const result = await RegexSecurityService
150
152
  .builder()
151
153
  .startOfLine()
152
154
  .nonCapturingGroup('[a-zA-Z]') // First letter
@@ -155,7 +157,7 @@ export class FormValidationComponent {
155
157
  .endOfLine()
156
158
  .timeout(2000)
157
159
  .execute(input, this.regexSecurity);
158
-
160
+
159
161
  return result.match;
160
162
  }
161
163
  }
@@ -167,10 +169,10 @@ export class FormValidationComponent {
167
169
 
168
170
  ```typescript
169
171
  interface RegexSecurityConfig {
170
- timeout?: number; // Timeout in ms (default: 5000)
171
- maxComplexity?: number; // Max complexity (default: 10)
172
+ timeout?: number; // Timeout in ms (default: 5000)
173
+ maxComplexity?: number; // Max complexity (default: 10)
172
174
  allowBacktracking?: boolean; // Allow backtracking (default: false)
173
- safeMode?: boolean; // Safe mode (default: false)
175
+ safeMode?: boolean; // Safe mode (default: false)
174
176
  }
175
177
  ```
176
178
 
@@ -178,12 +180,12 @@ interface RegexSecurityConfig {
178
180
 
179
181
  ```typescript
180
182
  interface RegexBuilderOptions {
181
- global?: boolean; // 'g' flag
182
- ignoreCase?: boolean; // 'i' flag
183
- multiline?: boolean; // 'm' flag
184
- dotAll?: boolean; // 's' flag
185
- unicode?: boolean; // 'u' flag
186
- sticky?: boolean; // 'y' flag
183
+ global?: boolean; // 'g' flag
184
+ ignoreCase?: boolean; // 'i' flag
185
+ multiline?: boolean; // 'm' flag
186
+ dotAll?: boolean; // 's' flag
187
+ unicode?: boolean; // 'u' flag
188
+ sticky?: boolean; // 'y' flag
187
189
  }
188
190
  ```
189
191
 
@@ -220,12 +222,12 @@ The service automatically detects:
220
222
 
221
223
  ```typescript
222
224
  interface RegexTestResult {
223
- match: boolean; // If there was a match
225
+ match: boolean; // If there was a match
224
226
  matches?: RegExpMatchArray[]; // All matches found
225
227
  groups?: { [key: string]: string }; // Captured groups
226
- executionTime: number; // Execution time in ms
227
- timeout: boolean; // If there was a timeout
228
- error?: string; // Error if one occurred
228
+ executionTime: number; // Execution time in ms
229
+ timeout: boolean; // If there was a timeout
230
+ error?: string; // Error if one occurred
229
231
  }
230
232
  ```
231
233
 
@@ -233,10 +235,10 @@ interface RegexTestResult {
233
235
 
234
236
  ```typescript
235
237
  interface RegexSecurityResult {
236
- safe: boolean; // If the pattern is safe
237
- complexity: number; // Complexity level (0-∞)
238
+ safe: boolean; // If the pattern is safe
239
+ complexity: number; // Complexity level (0-∞)
238
240
  risk: 'low' | 'medium' | 'high' | 'critical';
239
- warnings: string[]; // Security warnings
241
+ warnings: string[]; // Security warnings
240
242
  recommendations: string[]; // Improvement recommendations
241
243
  }
242
244
  ```
@@ -250,27 +252,27 @@ import { AbstractControl, ValidationErrors } from '@angular/forms';
250
252
 
251
253
  export class SecurityValidators {
252
254
  constructor(private regexSecurity: RegexSecurityService) {}
253
-
255
+
254
256
  async securePattern(pattern: string, config?: RegexSecurityConfig) {
255
257
  return async (control: AbstractControl): Promise<ValidationErrors | null> => {
256
258
  const value = control.value;
257
-
259
+
258
260
  if (!value) return null;
259
-
261
+
260
262
  try {
261
263
  const result = await this.regexSecurity.testRegex(pattern, value, config);
262
-
264
+
263
265
  if (!result.match) {
264
266
  return { securePattern: { value, reason: 'Pattern does not match' } };
265
267
  }
266
-
268
+
267
269
  if (result.timeout) {
268
270
  return { securePattern: { value, reason: 'Pattern execution timeout' } };
269
271
  }
270
-
272
+
271
273
  return null;
272
274
  } catch (error) {
273
- return { securePattern: { value, reason: error.message } };
275
+ return { securePattern: { value, reason: (error as Error).message } };
274
276
  }
275
277
  };
276
278
  }
@@ -282,11 +284,9 @@ export class SecurityValidators {
282
284
  ```typescript
283
285
  @Component({...})
284
286
  export class SecureFormComponent {
285
- constructor(
286
- private regexSecurity: RegexSecurityService,
287
- private securityValidators: SecurityValidators
288
- ) {}
289
-
287
+ private regexSecurity = inject(RegexSecurityService);
288
+ private securityValidators = inject(SecurityValidators);
289
+
290
290
  emailValidator = this.securityValidators.securePattern(
291
291
  '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
292
292
  { timeout: 3000, safeMode: true }
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DestroyRef, Injectable } from '@angular/core';
2
+ import { inject, DestroyRef, Injectable, makeEnvironmentProviders } from '@angular/core';
3
3
 
4
4
  /**
5
5
  * Security service for regular expressions that prevents ReDoS
@@ -28,14 +28,14 @@ class RegexSecurityService {
28
28
  match: false,
29
29
  executionTime: performance.now() - startTime,
30
30
  timeout: false,
31
- error: `Pattern rejected: ${securityCheck.warnings.join(', ')}`
31
+ error: `Pattern rejected: ${securityCheck.warnings.join(', ')}`,
32
32
  };
33
33
  }
34
34
  // Execute in Web Worker with timeout
35
35
  const result = await this.executeInWorker(pattern, text, finalConfig);
36
36
  return {
37
37
  ...result,
38
- executionTime: performance.now() - startTime
38
+ executionTime: performance.now() - startTime,
39
39
  };
40
40
  }
41
41
  catch (error) {
@@ -43,7 +43,7 @@ class RegexSecurityService {
43
43
  match: false,
44
44
  executionTime: performance.now() - startTime,
45
45
  timeout: false,
46
- error: error instanceof Error ? error.message : 'Unknown error'
46
+ error: error instanceof Error ? error.message : 'Unknown error',
47
47
  };
48
48
  }
49
49
  }
@@ -57,7 +57,11 @@ class RegexSecurityService {
57
57
  let risk = 'low';
58
58
  // Analysis of dangerous patterns
59
59
  const dangerousPatterns = [
60
- { pattern: /\*\*/, risk: 'high', message: 'Nested quantifiers (catastrophic backtracking)' },
60
+ {
61
+ pattern: /\*\*/,
62
+ risk: 'high',
63
+ message: 'Nested quantifiers (catastrophic backtracking)',
64
+ },
61
65
  { pattern: /\+\+/, risk: 'high', message: 'Nested plus quantifiers' },
62
66
  { pattern: /\(\?\=/, risk: 'medium', message: 'Lookahead assertions' },
63
67
  { pattern: /\(\?\!/, risk: 'medium', message: 'Negative lookahead' },
@@ -65,8 +69,16 @@ class RegexSecurityService {
65
69
  { pattern: /\(\?\</, risk: 'high', message: 'Lookbehind assertions' },
66
70
  { pattern: /\(\?\(\?\)/, risk: 'critical', message: 'Recursive patterns' },
67
71
  { pattern: /(\{(\d+,)?\d+\})/, risk: 'medium', message: 'Quantified repetition' },
68
- { pattern: /(\.\*)|(\.+)|(\.\?)/, risk: 'medium', message: 'Greedy quantifiers with dot' },
69
- { pattern: /(\[.*\*.*\])|(\[.*\+.*\])/, risk: 'medium', message: 'Character classes with quantifiers' }
72
+ {
73
+ pattern: /(\.\*)|(\.+)|(\.\?)/,
74
+ risk: 'medium',
75
+ message: 'Greedy quantifiers with dot',
76
+ },
77
+ {
78
+ pattern: /(\[.*\*.*\])|(\[.*\+.*\])/,
79
+ risk: 'medium',
80
+ message: 'Character classes with quantifiers',
81
+ },
70
82
  ];
71
83
  // Calculate complexity
72
84
  complexity = this.calculateComplexity(pattern);
@@ -96,7 +108,7 @@ class RegexSecurityService {
96
108
  complexity,
97
109
  risk,
98
110
  warnings,
99
- recommendations
111
+ recommendations,
100
112
  };
101
113
  }
102
114
  /**
@@ -118,8 +130,8 @@ class RegexSecurityService {
118
130
  data: {
119
131
  pattern,
120
132
  text,
121
- timeout: config.timeout || 5000
122
- }
133
+ timeout: config.timeout || 5000,
134
+ },
123
135
  };
124
136
  // Timeout for execution
125
137
  const timeoutId = setTimeout(() => {
@@ -129,7 +141,7 @@ class RegexSecurityService {
129
141
  match: false,
130
142
  executionTime: 0,
131
143
  timeout: true,
132
- error: 'Execution timeout'
144
+ error: 'Execution timeout',
133
145
  });
134
146
  }, config.timeout || 5000);
135
147
  worker.onmessage = (event) => {
@@ -148,7 +160,7 @@ class RegexSecurityService {
148
160
  match: false,
149
161
  executionTime: 0,
150
162
  timeout: false,
151
- error: `Worker error: ${error.message || 'Unknown error'}`
163
+ error: `Worker error: ${error.message || 'Unknown error'}`,
152
164
  });
153
165
  };
154
166
  worker.postMessage(task);
@@ -158,7 +170,7 @@ class RegexSecurityService {
158
170
  match: false,
159
171
  executionTime: 0,
160
172
  timeout: false,
161
- error: `Failed to create worker: ${error instanceof Error ? error.message : 'Unknown error'}`
173
+ error: `Failed to create worker: ${error instanceof Error ? error.message : 'Unknown error'}`,
162
174
  });
163
175
  }
164
176
  });
@@ -248,7 +260,7 @@ class RegexSecurityService {
248
260
  * Gets numeric risk level
249
261
  */
250
262
  getRiskLevel(risk) {
251
- const levels = { 'low': 1, 'medium': 2, 'high': 3, 'critical': 4 };
263
+ const levels = { low: 1, medium: 2, high: 3, critical: 4 };
252
264
  return levels[risk] || 0;
253
265
  }
254
266
  /**
@@ -259,14 +271,14 @@ class RegexSecurityService {
259
271
  timeout: config.timeout || 5000,
260
272
  maxComplexity: config.maxComplexity || 10,
261
273
  allowBacktracking: config.allowBacktracking || false,
262
- safeMode: config.safeMode || false
274
+ safeMode: config.safeMode || false,
263
275
  };
264
276
  }
265
277
  /**
266
278
  * Cleans up resources when the service is destroyed
267
279
  */
268
280
  ngOnDestroy() {
269
- this.workers.forEach(worker => {
281
+ this.workers.forEach((worker) => {
270
282
  worker.terminate();
271
283
  });
272
284
  this.workers.clear();
@@ -387,7 +399,7 @@ class RegexSecurityBuilder {
387
399
  return {
388
400
  pattern: this.patternValue,
389
401
  options: this.optionsValue,
390
- security: this.securityConfigValue
402
+ security: this.securityConfigValue,
391
403
  };
392
404
  }
393
405
  /**
@@ -399,9 +411,25 @@ class RegexSecurityBuilder {
399
411
  }
400
412
  }
401
413
 
414
+ const defaultSecurityConfig = {
415
+ enableRegexSecurity: true,
416
+ defaultTimeout: 5000,
417
+ safeMode: false,
418
+ };
419
+ function provideSecurity(config = {}) {
420
+ const mergedConfig = { ...defaultSecurityConfig, ...config };
421
+ const providers = [];
422
+ if (mergedConfig.enableRegexSecurity) {
423
+ providers.push(RegexSecurityService);
424
+ }
425
+ return makeEnvironmentProviders(providers);
426
+ }
427
+ function provideRegexSecurity() {
428
+ return makeEnvironmentProviders([RegexSecurityService]);
429
+ }
430
+
402
431
  /**
403
432
  * Generated bundle index. Do not edit.
404
433
  */
405
434
 
406
- export { RegexSecurityBuilder, RegexSecurityService };
407
- //# sourceMappingURL=angular-helpers-security.mjs.map
435
+ export { RegexSecurityBuilder, RegexSecurityService, defaultSecurityConfig, provideRegexSecurity, provideSecurity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular-helpers/security",
3
- "version": "21.0.1",
3
+ "version": "21.0.3",
4
4
  "description": "Angular security helpers for preventing ReDoS and other security vulnerabilities",
5
5
  "keywords": [
6
6
  "angular",
@@ -27,7 +27,6 @@
27
27
  "peerDependencies": {
28
28
  "@angular/common": "^21.0.0",
29
29
  "@angular/core": "^21.0.0",
30
- "@angular-helpers/browser-web-apis": "21.0.1",
31
30
  "rxjs": "^7.0.0 || ^8.0.0"
32
31
  },
33
32
  "dependencies": {
@@ -1,4 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
+ import { EnvironmentProviders } from '@angular/core';
2
3
 
3
4
  interface RegexSecurityConfig {
4
5
  timeout?: number;
@@ -150,5 +151,14 @@ declare class RegexSecurityBuilder {
150
151
  execute(text: string, service: RegexSecurityService): Promise<RegexTestResult>;
151
152
  }
152
153
 
153
- export { RegexSecurityBuilder, RegexSecurityService };
154
- export type { RegexBuilderOptions, RegexSecurityConfig, RegexSecurityResult, RegexTestResult };
154
+ interface SecurityConfig {
155
+ enableRegexSecurity?: boolean;
156
+ defaultTimeout?: number;
157
+ safeMode?: boolean;
158
+ }
159
+ declare const defaultSecurityConfig: SecurityConfig;
160
+ declare function provideSecurity(config?: SecurityConfig): EnvironmentProviders;
161
+ declare function provideRegexSecurity(): EnvironmentProviders;
162
+
163
+ export { RegexSecurityBuilder, RegexSecurityService, defaultSecurityConfig, provideRegexSecurity, provideSecurity };
164
+ export type { RegexBuilderOptions, RegexSecurityConfig, RegexSecurityResult, RegexTestResult, SecurityConfig };
@@ -1 +0,0 @@
1
- {"version":3,"file":"angular-helpers-security.mjs","sources":["../../../packages/security/src/services/regex-security.service.ts","../../../packages/security/src/angular-helpers-security.ts"],"sourcesContent":["import { Injectable, inject, DestroyRef } from '@angular/core';\nimport { Observable, Subject } from 'rxjs';\nimport { map, catchError, timeout } from 'rxjs/operators';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nexport interface RegexSecurityConfig {\n timeout?: number; // Timeout in milliseconds (default: 5000)\n maxComplexity?: number; // Maximum complexity allowed\n allowBacktracking?: boolean; // Allow catastrophic backtracking\n safeMode?: boolean; // Safe mode with secure patterns only\n}\n\nexport interface RegexTestResult {\n match: boolean;\n matches?: RegExpMatchArray[];\n groups?: { [key: string]: string };\n executionTime: number;\n timeout: boolean;\n error?: string;\n}\n\nexport interface RegexSecurityResult {\n safe: boolean;\n complexity: number;\n risk: 'low' | 'medium' | 'high' | 'critical';\n warnings: string[];\n recommendations: string[];\n}\n\nexport interface RegexBuilderOptions {\n global?: boolean;\n ignoreCase?: boolean;\n multiline?: boolean;\n dotAll?: boolean;\n unicode?: boolean;\n sticky?: boolean;\n}\n\n/**\n * Security service for regular expressions that prevents ReDoS\n * using Web Workers for safe execution with timeout\n */\n@Injectable()\nexport class RegexSecurityService {\n private destroyRef = inject(DestroyRef);\n private workers = new Map<string, Worker>();\n\n /**\n * Builder pattern to construct safe regular expressions\n */\n static builder(): RegexSecurityBuilder {\n return new RegexSecurityBuilder();\n }\n\n /**\n * Executes a regular expression safely with a timeout\n */\n async testRegex(\n pattern: string,\n text: string,\n config: RegexSecurityConfig = {}\n ): Promise<RegexTestResult> {\n const startTime = performance.now();\n const finalConfig = this.mergeConfig(config);\n\n try {\n // First, analyze pattern security\n const securityCheck = await this.analyzePatternSecurity(pattern);\n \n if (!securityCheck.safe && !finalConfig.safeMode) {\n return {\n match: false,\n executionTime: performance.now() - startTime,\n timeout: false,\n error: `Pattern rejected: ${securityCheck.warnings.join(', ')}`\n };\n }\n\n // Execute in Web Worker with timeout\n const result = await this.executeInWorker(pattern, text, finalConfig);\n \n return {\n ...result,\n executionTime: performance.now() - startTime\n };\n } catch (error) {\n return {\n match: false,\n executionTime: performance.now() - startTime,\n timeout: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n }\n\n /**\n * Analyzes the security of a regular expression pattern\n */\n async analyzePatternSecurity(pattern: string): Promise<RegexSecurityResult> {\n const warnings: string[] = [];\n const recommendations: string[] = [];\n let complexity = 0;\n let risk: 'low' | 'medium' | 'high' | 'critical' = 'low';\n\n // Analysis of dangerous patterns\n const dangerousPatterns = [\n { pattern: /\\*\\*/, risk: 'high' as const, message: 'Nested quantifiers (catastrophic backtracking)' },\n { pattern: /\\+\\+/, risk: 'high' as const, message: 'Nested plus quantifiers' },\n { pattern: /\\(\\?\\=/, risk: 'medium' as const, message: 'Lookahead assertions' },\n { pattern: /\\(\\?\\!/, risk: 'medium' as const, message: 'Negative lookahead' },\n { pattern: /\\(\\?\\:/, risk: 'low' as const, message: 'Non-capturing groups' },\n { pattern: /\\(\\?\\</, risk: 'high' as const, message: 'Lookbehind assertions' },\n { pattern: /\\(\\?\\(\\?\\)/, risk: 'critical' as const, message: 'Recursive patterns' },\n { pattern: /(\\{(\\d+,)?\\d+\\})/, risk: 'medium' as const, message: 'Quantified repetition' },\n { pattern: /(\\.\\*)|(\\.+)|(\\.\\?)/, risk: 'medium' as const, message: 'Greedy quantifiers with dot' },\n { pattern: /(\\[.*\\*.*\\])|(\\[.*\\+.*\\])/, risk: 'medium' as const, message: 'Character classes with quantifiers' }\n ];\n\n // Calculate complexity\n complexity = this.calculateComplexity(pattern);\n\n // Evaluate dangerous patterns\n for (const dangerous of dangerousPatterns) {\n if (dangerous.pattern.test(pattern)) {\n warnings.push(dangerous.message);\n if (this.getRiskLevel(dangerous.risk) > this.getRiskLevel(risk)) {\n risk = dangerous.risk;\n }\n }\n }\n\n // Recommendations based on the analysis\n if (complexity > 10) {\n recommendations.push('Consider simplifying the pattern');\n risk = this.getRiskLevel(risk) > this.getRiskLevel('high') ? risk : 'high';\n }\n\n if (pattern.includes('**') || pattern.includes('++')) {\n recommendations.push('Avoid nested quantifiers to prevent catastrophic backtracking');\n }\n\n if (pattern.length > 100) {\n recommendations.push('Long patterns are harder to maintain and may impact performance');\n }\n\n const safe = risk !== 'critical' && warnings.length === 0;\n\n return {\n safe,\n complexity,\n risk,\n warnings,\n recommendations\n };\n }\n\n /**\n * Executes the regular expression in a Web Worker\n */\n private async executeInWorker(\n pattern: string,\n text: string,\n config: RegexSecurityConfig\n ): Promise<RegexTestResult> {\n return new Promise((resolve) => {\n const workerName = `regex-worker-${Date.now()}`;\n \n try {\n // Create temporary worker\n const workerCode = this.generateWorkerCode();\n const blob = new Blob([workerCode], { type: 'application/javascript' });\n const worker = new Worker(URL.createObjectURL(blob));\n \n this.workers.set(workerName, worker);\n\n const taskId = `regex_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n \n const task = {\n id: taskId,\n type: 'regex-test',\n data: {\n pattern,\n text,\n timeout: config.timeout || 5000\n }\n };\n\n // Timeout for execution\n const timeoutId = setTimeout(() => {\n worker.terminate();\n this.workers.delete(workerName);\n resolve({\n match: false,\n executionTime: 0,\n timeout: true,\n error: 'Execution timeout'\n });\n }, config.timeout || 5000);\n\n worker.onmessage = (event) => {\n clearTimeout(timeoutId);\n worker.terminate();\n this.workers.delete(workerName);\n \n if (event.data.id === taskId) {\n resolve(event.data.data as RegexTestResult);\n }\n };\n\n worker.onerror = (error) => {\n clearTimeout(timeoutId);\n worker.terminate();\n this.workers.delete(workerName);\n resolve({\n match: false,\n executionTime: 0,\n timeout: false,\n error: `Worker error: ${error.message || 'Unknown error'}`\n });\n };\n\n worker.postMessage(task);\n } catch (error) {\n resolve({\n match: false,\n executionTime: 0,\n timeout: false,\n error: `Failed to create worker: ${error instanceof Error ? error.message : 'Unknown error'}`\n });\n }\n });\n }\n\n /**\n * Generates the Web Worker code\n */\n private generateWorkerCode(): string {\n return `\n self.addEventListener('message', function(event) {\n const task = event.data;\n \n if (task.type === 'regex-test') {\n const { pattern, text, timeout } = task.data;\n const startTime = performance.now();\n \n try {\n const regex = new RegExp(pattern, 'g');\n const matches = [];\n let match;\n \n while ((match = regex.exec(text)) !== null) {\n matches.push([...match]);\n \n // Prevention of infinite loops\n if (matches.length > 1000) {\n throw new Error('Too many matches - possible infinite loop');\n }\n }\n \n const groups = {};\n if (matches.length > 0) {\n const firstMatch = matches[0];\n for (let i = 1; i < firstMatch.length; i++) {\n groups[\\`group\\${i}\\`] = firstMatch[i];\n }\n }\n \n self.postMessage({\n id: task.id,\n type: 'regex-result',\n data: {\n match: matches.length > 0,\n matches,\n groups,\n executionTime: performance.now() - startTime,\n timeout: false\n }\n });\n } catch (error) {\n self.postMessage({\n id: task.id,\n type: 'regex-result',\n data: {\n match: false,\n executionTime: performance.now() - startTime,\n timeout: false,\n error: error.message || 'Execution error'\n }\n });\n }\n }\n });\n `;\n }\n\n /**\n * Calculates the complexity of a pattern\n */\n private calculateComplexity(pattern: string): number {\n let complexity = 0;\n \n // Nested quantifiers increase complexity\n complexity += (pattern.match(/\\*\\*/g) || []).length * 5;\n complexity += (pattern.match(/\\+\\+/g) || []).length * 5;\n complexity += (pattern.match(/\\?\\?/g) || []).length * 3;\n \n // Lookaheads/lookbehinds\n complexity += (pattern.match(/\\(\\?\\=/g) || []).length * 2;\n complexity += (pattern.match(/\\(\\?\\!/g) || []).length * 2;\n complexity += (pattern.match(/\\(\\?\\</g) || []).length * 3;\n \n // Nested groups\n const openParens = (pattern.match(/\\(/g) || []).length;\n complexity += openParens * 0.5;\n \n // Pattern length\n complexity += pattern.length * 0.01;\n \n return Math.round(complexity * 100) / 100;\n }\n\n /**\n * Gets numeric risk level\n */\n private getRiskLevel(risk: 'low' | 'medium' | 'high' | 'critical'): number {\n const levels = { 'low': 1, 'medium': 2, 'high': 3, 'critical': 4 };\n return levels[risk] || 0;\n }\n\n /**\n * Merges configuration with default values\n */\n private mergeConfig(config: RegexSecurityConfig): Required<RegexSecurityConfig> {\n return {\n timeout: config.timeout || 5000,\n maxComplexity: config.maxComplexity || 10,\n allowBacktracking: config.allowBacktracking || false,\n safeMode: config.safeMode || false\n };\n }\n\n /**\n * Cleans up resources when the service is destroyed\n */\n ngOnDestroy(): void {\n this.workers.forEach(worker => {\n worker.terminate();\n });\n this.workers.clear();\n }\n}\n\n/**\n * Builder pattern to construct safe regular expressions\n */\nexport class RegexSecurityBuilder {\n private patternValue: string = '';\n private optionsValue: RegexBuilderOptions = {};\n private securityConfigValue: RegexSecurityConfig = {};\n\n /**\n * Defines the base pattern\n */\n pattern(pattern: string): RegexSecurityBuilder {\n this.patternValue = pattern;\n return this;\n }\n\n /**\n * Appends text to the current pattern\n */\n append(text: string): RegexSecurityBuilder {\n this.patternValue += text;\n return this;\n }\n\n /**\n * Adds a capturing group\n */\n group(content: string, name?: string): RegexSecurityBuilder {\n if (name) {\n this.patternValue += `(?<${name}>${content})`;\n } else {\n this.patternValue += `(${content})`;\n }\n return this;\n }\n\n /**\n * Adds a non-capturing group\n */\n nonCapturingGroup(content: string): RegexSecurityBuilder {\n this.patternValue += `(?:${content})`;\n return this;\n }\n\n /**\n * Adds an alternative\n */\n or(alternative: string): RegexSecurityBuilder {\n this.patternValue += `|${alternative}`;\n return this;\n }\n\n /**\n * Adds a quantifier\n */\n quantifier(quantifier: '*' | '+' | '?' | '{n}' | '{n,}' | '{n,m}'): RegexSecurityBuilder {\n this.patternValue += quantifier;\n return this;\n }\n\n /**\n * Adds a character set\n */\n characterSet(chars: string, negate = false): RegexSecurityBuilder {\n this.patternValue += `[${negate ? '^' : ''}${chars}]`;\n return this;\n }\n\n /**\n * Adds a start of line anchor\n */\n startOfLine(): RegexSecurityBuilder {\n this.patternValue += '^';\n return this;\n }\n\n /**\n * Adds an end of line anchor\n */\n endOfLine(): RegexSecurityBuilder {\n this.patternValue += '$';\n return this;\n }\n\n /**\n * Configures regular expression options\n */\n options(options: RegexBuilderOptions): RegexSecurityBuilder {\n this.optionsValue = { ...this.optionsValue, ...options };\n return this;\n }\n\n /**\n * Configures security options\n */\n security(config: RegexSecurityConfig): RegexSecurityBuilder {\n this.securityConfigValue = { ...this.securityConfigValue, ...config };\n return this;\n }\n\n /**\n * Configures timeout\n */\n timeout(ms: number): RegexSecurityBuilder {\n this.securityConfigValue.timeout = ms;\n return this;\n }\n\n /**\n * Activates safe mode\n */\n safeMode(): RegexSecurityBuilder {\n this.securityConfigValue.safeMode = true;\n return this;\n }\n\n /**\n * Builds the final regular expression\n */\n build(): { pattern: string; options: RegexBuilderOptions; security: RegexSecurityConfig } {\n return {\n pattern: this.patternValue,\n options: this.optionsValue,\n security: this.securityConfigValue\n };\n }\n\n /**\n * Builds and executes the regular expression\n */\n async execute(text: string, service: RegexSecurityService): Promise<RegexTestResult> {\n const { pattern, security } = this.build();\n return service.testRegex(pattern, text, security);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}