@sparkleideas/security 3.0.0-alpha.22 → 3.0.0-alpha.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/CVE-REMEDIATION.d.ts +86 -0
  2. package/dist/CVE-REMEDIATION.d.ts.map +1 -0
  3. package/dist/CVE-REMEDIATION.js +221 -0
  4. package/dist/CVE-REMEDIATION.js.map +1 -0
  5. package/dist/application/index.d.ts +7 -0
  6. package/dist/application/index.d.ts.map +1 -0
  7. package/dist/application/index.js +7 -0
  8. package/dist/application/index.js.map +1 -0
  9. package/dist/application/services/security-application-service.d.ts +71 -0
  10. package/dist/application/services/security-application-service.d.ts.map +1 -0
  11. package/dist/application/services/security-application-service.js +153 -0
  12. package/dist/application/services/security-application-service.js.map +1 -0
  13. package/dist/credential-generator.d.ts +176 -0
  14. package/dist/credential-generator.d.ts.map +1 -0
  15. package/dist/credential-generator.js +272 -0
  16. package/dist/credential-generator.js.map +1 -0
  17. package/dist/domain/entities/security-context.d.ts +68 -0
  18. package/dist/domain/entities/security-context.d.ts.map +1 -0
  19. package/dist/domain/entities/security-context.js +132 -0
  20. package/dist/domain/entities/security-context.js.map +1 -0
  21. package/dist/domain/index.d.ts +8 -0
  22. package/dist/domain/index.d.ts.map +1 -0
  23. package/dist/domain/index.js +8 -0
  24. package/dist/domain/index.js.map +1 -0
  25. package/dist/domain/services/security-domain-service.d.ts +71 -0
  26. package/dist/domain/services/security-domain-service.d.ts.map +1 -0
  27. package/dist/domain/services/security-domain-service.js +237 -0
  28. package/dist/domain/services/security-domain-service.js.map +1 -0
  29. package/dist/index.d.ts +119 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +145 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/input-validator.d.ts +338 -0
  34. package/dist/input-validator.d.ts.map +1 -0
  35. package/dist/input-validator.js +393 -0
  36. package/dist/input-validator.js.map +1 -0
  37. package/dist/password-hasher.d.ts +128 -0
  38. package/dist/password-hasher.d.ts.map +1 -0
  39. package/dist/password-hasher.js +183 -0
  40. package/dist/password-hasher.js.map +1 -0
  41. package/dist/path-validator.d.ts +148 -0
  42. package/dist/path-validator.d.ts.map +1 -0
  43. package/dist/path-validator.js +421 -0
  44. package/dist/path-validator.js.map +1 -0
  45. package/dist/safe-executor.d.ts +173 -0
  46. package/dist/safe-executor.d.ts.map +1 -0
  47. package/dist/safe-executor.js +370 -0
  48. package/dist/safe-executor.js.map +1 -0
  49. package/dist/token-generator.d.ts +224 -0
  50. package/dist/token-generator.d.ts.map +1 -0
  51. package/dist/token-generator.js +351 -0
  52. package/dist/token-generator.js.map +1 -0
  53. package/package.json +1 -1
  54. package/tsconfig.build.tsbuildinfo +1 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Safe Executor - HIGH-1 Remediation
3
+ *
4
+ * Fixes command injection vulnerabilities by:
5
+ * - Using execFile instead of exec with shell
6
+ * - Validating all command arguments
7
+ * - Implementing command allowlist
8
+ * - Sanitizing command inputs
9
+ *
10
+ * Security Properties:
11
+ * - No shell interpretation
12
+ * - Argument validation
13
+ * - Command allowlist enforcement
14
+ * - Timeout controls
15
+ * - Resource limits
16
+ *
17
+ * @module v3/security/safe-executor
18
+ */
19
+ import { execFile, spawn } from 'child_process';
20
+ import { promisify } from 'util';
21
+ import * as path from 'path';
22
+ const execFileAsync = promisify(execFile);
23
+ export class SafeExecutorError extends Error {
24
+ code;
25
+ command;
26
+ args;
27
+ constructor(message, code, command, args) {
28
+ super(message);
29
+ this.code = code;
30
+ this.command = command;
31
+ this.args = args;
32
+ this.name = 'SafeExecutorError';
33
+ }
34
+ }
35
+ /**
36
+ * Default blocked argument patterns.
37
+ * These patterns indicate potential command injection attempts.
38
+ */
39
+ const DEFAULT_BLOCKED_PATTERNS = [
40
+ // Shell metacharacters
41
+ ';',
42
+ '&&',
43
+ '||',
44
+ '|',
45
+ '`',
46
+ '$(',
47
+ '${',
48
+ // Redirection
49
+ '>',
50
+ '<',
51
+ '>>',
52
+ // Background execution
53
+ '&',
54
+ // Newlines (command chaining)
55
+ '\n',
56
+ '\r',
57
+ // Null byte injection
58
+ '\0',
59
+ // Command substitution
60
+ '$()',
61
+ ];
62
+ /**
63
+ * Commands that are inherently dangerous and should never be allowed.
64
+ */
65
+ const DANGEROUS_COMMANDS = [
66
+ 'rm',
67
+ 'rmdir',
68
+ 'del',
69
+ 'format',
70
+ 'mkfs',
71
+ 'dd',
72
+ 'chmod',
73
+ 'chown',
74
+ 'kill',
75
+ 'killall',
76
+ 'pkill',
77
+ 'reboot',
78
+ 'shutdown',
79
+ 'init',
80
+ 'poweroff',
81
+ 'halt',
82
+ ];
83
+ /**
84
+ * Safe command executor that prevents command injection.
85
+ *
86
+ * This class replaces unsafe exec() and spawn({shell: true}) calls
87
+ * with validated execFile() calls.
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const executor = new SafeExecutor({
92
+ * allowedCommands: ['git', 'npm', 'node']
93
+ * });
94
+ *
95
+ * const result = await executor.execute('git', ['status']);
96
+ * ```
97
+ */
98
+ export class SafeExecutor {
99
+ config;
100
+ blockedPatterns;
101
+ constructor(config) {
102
+ this.config = {
103
+ allowedCommands: config.allowedCommands,
104
+ blockedPatterns: config.blockedPatterns ?? DEFAULT_BLOCKED_PATTERNS,
105
+ timeout: config.timeout ?? 30000,
106
+ maxBuffer: config.maxBuffer ?? 10 * 1024 * 1024, // 10MB
107
+ cwd: config.cwd ?? process.cwd(),
108
+ env: config.env ?? process.env,
109
+ allowSudo: config.allowSudo ?? false,
110
+ };
111
+ // Compile blocked patterns for performance
112
+ this.blockedPatterns = this.config.blockedPatterns.map(pattern => new RegExp(this.escapeRegExp(pattern), 'i'));
113
+ this.validateConfig();
114
+ }
115
+ /**
116
+ * Escapes special regex characters.
117
+ */
118
+ escapeRegExp(str) {
119
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
120
+ }
121
+ /**
122
+ * Validates executor configuration.
123
+ */
124
+ validateConfig() {
125
+ if (this.config.allowedCommands.length === 0) {
126
+ throw new SafeExecutorError('At least one allowed command must be specified', 'EMPTY_ALLOWLIST');
127
+ }
128
+ // Check for dangerous commands in allowlist
129
+ const dangerousAllowed = this.config.allowedCommands.filter(cmd => DANGEROUS_COMMANDS.includes(path.basename(cmd)));
130
+ if (dangerousAllowed.length > 0) {
131
+ throw new SafeExecutorError(`Dangerous commands cannot be allowed: ${dangerousAllowed.join(', ')}`, 'DANGEROUS_COMMAND_ALLOWED');
132
+ }
133
+ }
134
+ /**
135
+ * Validates a command against the allowlist.
136
+ *
137
+ * @param command - Command to validate
138
+ * @throws SafeExecutorError if command is not allowed
139
+ */
140
+ validateCommand(command) {
141
+ const basename = path.basename(command);
142
+ // Check if command is allowed
143
+ const isAllowed = this.config.allowedCommands.some(allowed => {
144
+ const allowedBasename = path.basename(allowed);
145
+ return command === allowed || basename === allowedBasename;
146
+ });
147
+ if (!isAllowed) {
148
+ throw new SafeExecutorError(`Command not in allowlist: ${command}`, 'COMMAND_NOT_ALLOWED', command);
149
+ }
150
+ // Check for sudo
151
+ if (!this.config.allowSudo && (command === 'sudo' || basename === 'sudo')) {
152
+ throw new SafeExecutorError('Sudo commands are not allowed', 'SUDO_NOT_ALLOWED', command);
153
+ }
154
+ }
155
+ /**
156
+ * Validates command arguments for injection patterns.
157
+ *
158
+ * @param args - Arguments to validate
159
+ * @throws SafeExecutorError if arguments contain dangerous patterns
160
+ */
161
+ validateArguments(args) {
162
+ for (const arg of args) {
163
+ // Check for null bytes
164
+ if (arg.includes('\0')) {
165
+ throw new SafeExecutorError('Null byte detected in argument', 'NULL_BYTE_INJECTION', undefined, args);
166
+ }
167
+ // Check against blocked patterns
168
+ for (const pattern of this.blockedPatterns) {
169
+ if (pattern.test(arg)) {
170
+ throw new SafeExecutorError(`Dangerous pattern detected in argument: ${arg}`, 'DANGEROUS_PATTERN', undefined, args);
171
+ }
172
+ }
173
+ // Check for command chaining attempts
174
+ if (/^-.*[;&|]/.test(arg)) {
175
+ throw new SafeExecutorError(`Potential command chaining in argument: ${arg}`, 'COMMAND_CHAINING', undefined, args);
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * Sanitizes a single argument.
181
+ *
182
+ * @param arg - Argument to sanitize
183
+ * @returns Sanitized argument
184
+ */
185
+ sanitizeArgument(arg) {
186
+ // Remove null bytes
187
+ let sanitized = arg.replace(/\0/g, '');
188
+ // Remove shell metacharacters
189
+ sanitized = sanitized.replace(/[;&|`$(){}><\n\r]/g, '');
190
+ return sanitized;
191
+ }
192
+ /**
193
+ * Executes a command safely.
194
+ *
195
+ * @param command - Command to execute (must be in allowlist)
196
+ * @param args - Command arguments
197
+ * @returns Execution result
198
+ * @throws SafeExecutorError on validation failure or execution error
199
+ */
200
+ async execute(command, args = []) {
201
+ const startTime = Date.now();
202
+ // Validate command
203
+ this.validateCommand(command);
204
+ // Validate arguments
205
+ this.validateArguments(args);
206
+ try {
207
+ // Execute command WITHOUT shell
208
+ const { stdout, stderr } = await execFileAsync(command, args, {
209
+ cwd: this.config.cwd,
210
+ env: this.config.env,
211
+ timeout: this.config.timeout,
212
+ maxBuffer: this.config.maxBuffer,
213
+ shell: false, // CRITICAL: Never use shell
214
+ windowsHide: true,
215
+ });
216
+ return {
217
+ stdout: stdout.toString(),
218
+ stderr: stderr.toString(),
219
+ exitCode: 0,
220
+ command,
221
+ args,
222
+ duration: Date.now() - startTime,
223
+ };
224
+ }
225
+ catch (error) {
226
+ // Handle execution errors
227
+ if (error.killed) {
228
+ throw new SafeExecutorError('Command execution timed out', 'TIMEOUT', command, args);
229
+ }
230
+ if (error.code === 'ENOENT') {
231
+ throw new SafeExecutorError(`Command not found: ${command}`, 'COMMAND_NOT_FOUND', command, args);
232
+ }
233
+ // Return result with non-zero exit code
234
+ return {
235
+ stdout: error.stdout?.toString() ?? '',
236
+ stderr: error.stderr?.toString() ?? error.message,
237
+ exitCode: error.code ?? 1,
238
+ command,
239
+ args,
240
+ duration: Date.now() - startTime,
241
+ };
242
+ }
243
+ }
244
+ /**
245
+ * Executes a command with streaming output.
246
+ *
247
+ * @param command - Command to execute
248
+ * @param args - Command arguments
249
+ * @returns Streaming executor with process handles
250
+ */
251
+ executeStreaming(command, args = []) {
252
+ const startTime = Date.now();
253
+ // Validate command
254
+ this.validateCommand(command);
255
+ // Validate arguments
256
+ this.validateArguments(args);
257
+ // Spawn process WITHOUT shell
258
+ const childProcess = spawn(command, args, {
259
+ cwd: this.config.cwd,
260
+ env: this.config.env,
261
+ timeout: this.config.timeout,
262
+ shell: false, // CRITICAL: Never use shell
263
+ windowsHide: true,
264
+ });
265
+ const promise = new Promise((resolve, reject) => {
266
+ let stdout = '';
267
+ let stderr = '';
268
+ childProcess.stdout?.on('data', (data) => {
269
+ stdout += data.toString();
270
+ });
271
+ childProcess.stderr?.on('data', (data) => {
272
+ stderr += data.toString();
273
+ });
274
+ childProcess.on('close', (code) => {
275
+ resolve({
276
+ stdout,
277
+ stderr,
278
+ exitCode: code ?? 0,
279
+ command,
280
+ args,
281
+ duration: Date.now() - startTime,
282
+ });
283
+ });
284
+ childProcess.on('error', (error) => {
285
+ reject(new SafeExecutorError(error.message, 'EXECUTION_ERROR', command, args));
286
+ });
287
+ });
288
+ return {
289
+ process: childProcess,
290
+ stdout: childProcess.stdout,
291
+ stderr: childProcess.stderr,
292
+ promise,
293
+ };
294
+ }
295
+ /**
296
+ * Adds a command to the allowlist at runtime.
297
+ *
298
+ * @param command - Command to add
299
+ */
300
+ allowCommand(command) {
301
+ const basename = path.basename(command);
302
+ if (DANGEROUS_COMMANDS.includes(basename)) {
303
+ throw new SafeExecutorError(`Cannot allow dangerous command: ${command}`, 'DANGEROUS_COMMAND');
304
+ }
305
+ if (!this.config.allowedCommands.includes(command)) {
306
+ this.config.allowedCommands.push(command);
307
+ }
308
+ }
309
+ /**
310
+ * Checks if a command is allowed.
311
+ *
312
+ * @param command - Command to check
313
+ * @returns True if command is allowed
314
+ */
315
+ isCommandAllowed(command) {
316
+ const basename = path.basename(command);
317
+ return this.config.allowedCommands.some(allowed => {
318
+ const allowedBasename = path.basename(allowed);
319
+ return command === allowed || basename === allowedBasename;
320
+ });
321
+ }
322
+ /**
323
+ * Returns the current allowlist.
324
+ */
325
+ getAllowedCommands() {
326
+ return [...this.config.allowedCommands];
327
+ }
328
+ }
329
+ /**
330
+ * Factory function to create a safe executor for common development tasks.
331
+ *
332
+ * @returns Configured SafeExecutor for git, npm, and node
333
+ */
334
+ export function createDevelopmentExecutor() {
335
+ return new SafeExecutor({
336
+ allowedCommands: [
337
+ 'git',
338
+ 'npm',
339
+ 'npx',
340
+ 'node',
341
+ 'tsc',
342
+ 'vitest',
343
+ 'eslint',
344
+ 'prettier',
345
+ ],
346
+ });
347
+ }
348
+ /**
349
+ * Factory function to create a read-only executor.
350
+ * Only allows commands that read without modifying.
351
+ *
352
+ * @returns Configured SafeExecutor for read operations
353
+ */
354
+ export function createReadOnlyExecutor() {
355
+ return new SafeExecutor({
356
+ allowedCommands: [
357
+ 'git',
358
+ 'cat',
359
+ 'head',
360
+ 'tail',
361
+ 'ls',
362
+ 'find',
363
+ 'grep',
364
+ 'which',
365
+ 'echo',
366
+ ],
367
+ timeout: 10000,
368
+ });
369
+ }
370
+ //# sourceMappingURL=safe-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-executor.js","sourceRoot":"","sources":["../src/safe-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Token Generator - Secure Token Generation
3
+ *
4
+ * Provides cryptographically secure token generation for:
5
+ * - JWT tokens
6
+ * - Session tokens
7
+ * - CSRF tokens
8
+ * - API tokens
9
+ * - Verification codes
10
+ *
11
+ * Security Properties:
12
+ * - Uses crypto.randomBytes for all randomness
13
+ * - Configurable entropy levels
14
+ * - Timing-safe comparison
15
+ * - Token expiration handling
16
+ *
17
+ * @module v3/security/token-generator
18
+ */
19
+ export interface TokenConfig {
20
+ /**
21
+ * Default token length in bytes.
22
+ * Default: 32 (256 bits)
23
+ */
24
+ defaultLength?: number;
25
+ /**
26
+ * Token encoding format.
27
+ * Default: 'base64url'
28
+ */
29
+ encoding?: 'hex' | 'base64' | 'base64url';
30
+ /**
31
+ * HMAC secret for signed tokens.
32
+ */
33
+ hmacSecret?: string;
34
+ /**
35
+ * Default expiration time in seconds.
36
+ * Default: 3600 (1 hour)
37
+ */
38
+ defaultExpiration?: number;
39
+ }
40
+ export interface Token {
41
+ value: string;
42
+ createdAt: Date;
43
+ expiresAt: Date;
44
+ metadata?: Record<string, unknown>;
45
+ }
46
+ export interface SignedToken {
47
+ token: string;
48
+ signature: string;
49
+ combined: string;
50
+ createdAt: Date;
51
+ expiresAt: Date;
52
+ }
53
+ export interface VerificationCode {
54
+ code: string;
55
+ createdAt: Date;
56
+ expiresAt: Date;
57
+ attempts: number;
58
+ maxAttempts: number;
59
+ }
60
+ export declare class TokenGeneratorError extends Error {
61
+ readonly code: string;
62
+ constructor(message: string, code: string);
63
+ }
64
+ /**
65
+ * Secure token generator.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const generator = new TokenGenerator({ hmacSecret: 'secret' });
70
+ *
71
+ * // Generate session token
72
+ * const session = generator.generateSessionToken();
73
+ *
74
+ * // Generate signed token
75
+ * const signed = generator.generateSignedToken({ userId: '123' });
76
+ *
77
+ * // Verify signed token
78
+ * const isValid = generator.verifySignedToken(signed.combined);
79
+ * ```
80
+ */
81
+ export declare class TokenGenerator {
82
+ private readonly config;
83
+ constructor(config?: TokenConfig);
84
+ /**
85
+ * Generates a random token.
86
+ *
87
+ * @param length - Token length in bytes
88
+ * @returns Random token string
89
+ */
90
+ generate(length?: number): string;
91
+ /**
92
+ * Generates a token with expiration.
93
+ *
94
+ * @param expirationSeconds - Expiration time in seconds
95
+ * @param metadata - Optional metadata to attach
96
+ * @returns Token with expiration
97
+ */
98
+ generateWithExpiration(expirationSeconds?: number, metadata?: Record<string, unknown>): Token;
99
+ /**
100
+ * Generates a session token (URL-safe).
101
+ *
102
+ * @param length - Token length in bytes (default: 32)
103
+ * @returns Session token
104
+ */
105
+ generateSessionToken(length?: number): Token;
106
+ /**
107
+ * Generates a CSRF token.
108
+ *
109
+ * @returns CSRF token (shorter expiration)
110
+ */
111
+ generateCsrfToken(): Token;
112
+ /**
113
+ * Generates an API token with prefix.
114
+ *
115
+ * @param prefix - Token prefix (e.g., 'cf_')
116
+ * @returns Prefixed API token
117
+ */
118
+ generateApiToken(prefix?: string): Token;
119
+ /**
120
+ * Generates a numeric verification code.
121
+ *
122
+ * @param length - Number of digits (default: 6)
123
+ * @param expirationMinutes - Expiration in minutes (default: 10)
124
+ * @param maxAttempts - Maximum verification attempts (default: 3)
125
+ * @returns Verification code
126
+ */
127
+ generateVerificationCode(length?: number, expirationMinutes?: number, maxAttempts?: number): VerificationCode;
128
+ /**
129
+ * Generates a signed token using HMAC.
130
+ *
131
+ * @param payload - Data to include in token
132
+ * @param expirationSeconds - Token expiration
133
+ * @returns Signed token
134
+ */
135
+ generateSignedToken(payload: Record<string, unknown>, expirationSeconds?: number): SignedToken;
136
+ /**
137
+ * Verifies a signed token.
138
+ *
139
+ * @param combined - Combined token string (token.signature)
140
+ * @returns Decoded payload if valid, null otherwise
141
+ */
142
+ verifySignedToken(combined: string): Record<string, unknown> | null;
143
+ /**
144
+ * Generates a refresh token pair.
145
+ *
146
+ * @returns Access and refresh tokens
147
+ */
148
+ generateTokenPair(): {
149
+ accessToken: Token;
150
+ refreshToken: Token;
151
+ };
152
+ /**
153
+ * Generates a password reset token.
154
+ *
155
+ * @returns Password reset token (short expiration)
156
+ */
157
+ generatePasswordResetToken(): Token;
158
+ /**
159
+ * Generates an email verification token.
160
+ *
161
+ * @returns Email verification token
162
+ */
163
+ generateEmailVerificationToken(): Token;
164
+ /**
165
+ * Generates a unique request ID.
166
+ *
167
+ * @returns Request ID (shorter, for logging)
168
+ */
169
+ generateRequestId(): string;
170
+ /**
171
+ * Generates a correlation ID for distributed tracing.
172
+ *
173
+ * @returns Correlation ID
174
+ */
175
+ generateCorrelationId(): string;
176
+ /**
177
+ * Checks if a token has expired.
178
+ *
179
+ * @param token - Token to check
180
+ * @returns True if expired
181
+ */
182
+ isExpired(token: Token | VerificationCode): boolean;
183
+ /**
184
+ * Compares two tokens in constant time.
185
+ *
186
+ * @param a - First token
187
+ * @param b - Second token
188
+ * @returns True if equal
189
+ */
190
+ compare(a: string, b: string): boolean;
191
+ /**
192
+ * Signs data using HMAC-SHA256.
193
+ */
194
+ private sign;
195
+ /**
196
+ * Encodes bytes according to configuration.
197
+ */
198
+ private encode;
199
+ }
200
+ /**
201
+ * Factory function to create a production token generator.
202
+ *
203
+ * @param hmacSecret - HMAC secret for signed tokens
204
+ * @returns Configured TokenGenerator
205
+ */
206
+ export declare function createTokenGenerator(hmacSecret: string): TokenGenerator;
207
+ /**
208
+ * Gets or creates the default token generator.
209
+ * Note: Does not support signed tokens without configuration.
210
+ */
211
+ export declare function getDefaultGenerator(): TokenGenerator;
212
+ /**
213
+ * Quick token generation functions.
214
+ */
215
+ export declare const quickGenerate: {
216
+ token: (length?: number) => string;
217
+ sessionToken: () => Token;
218
+ csrfToken: () => Token;
219
+ apiToken: (prefix?: string) => Token;
220
+ verificationCode: (length?: number) => VerificationCode;
221
+ requestId: () => string;
222
+ correlationId: () => string;
223
+ };
224
+ //# sourceMappingURL=token-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-generator.d.ts","sourceRoot":"","sources":["../src/token-generator.ts"],"names":[],"mappings":"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"}