@scallywag/validation 1.0.0 → 1.0.4

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.
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Validation Middleware
3
+ *
4
+ * Next.js API route validation middleware using Zod
5
+ */
6
+ import { NextResponse } from 'next/server';
7
+ import { SecurityLevel, } from './types';
8
+ import { formatValidationErrors, validateData } from './validators';
9
+ import { MemoryRateLimitStore } from '@scallywag/gateway/middleware/security/RateLimiter';
10
+ import { logger } from '@scallywag/security/logger';
11
+ /**
12
+ * Helper function to extract request body safely
13
+ */
14
+ async function extractRequestBody(request) {
15
+ return await request.json().catch(() => ({}));
16
+ }
17
+ /**
18
+ * Helper function to safely extract validated data from result
19
+ * Extracted for better testability
20
+ */
21
+ export function safeExtractValidatedData(result) {
22
+ return typeof result === 'object' &&
23
+ result !== null &&
24
+ 'validatedData' in result
25
+ ? result['validatedData']
26
+ : {};
27
+ }
28
+ /**
29
+ * Helper function to validate request body
30
+ */
31
+ async function validateRequestBody(config, request, errors, validatedData) {
32
+ if (!config || request.method === 'GET')
33
+ return;
34
+ const body = await extractRequestBody(request);
35
+ const bodyResult = await validateData(config, body);
36
+ if (!bodyResult.success) {
37
+ errors.push(...bodyResult.errors);
38
+ }
39
+ else {
40
+ validatedData['body'] = bodyResult.data;
41
+ }
42
+ }
43
+ /**
44
+ * Helper function to validate query parameters
45
+ */
46
+ async function validateRequestQuery(config, request, errors, validatedData) {
47
+ if (!config)
48
+ return;
49
+ const url = new URL(request.url);
50
+ const queryParams = Object.fromEntries(url.searchParams.entries());
51
+ const queryResult = await validateData(config, queryParams);
52
+ if (!queryResult.success) {
53
+ errors.push(...queryResult.errors);
54
+ }
55
+ else {
56
+ validatedData['query'] = queryResult.data;
57
+ }
58
+ }
59
+ /**
60
+ * Helper function to validate headers
61
+ */
62
+ async function validateRequestHeaders(config, request, errors, validatedData) {
63
+ if (!config)
64
+ return;
65
+ // Convert Headers to plain object (safely iterate over header entries)
66
+ const headers = {};
67
+ request.headers.forEach((value, key) => {
68
+ // Safe to use bracket notation here since we're creating a new object
69
+ // and headers from NextRequest are guaranteed to be strings
70
+ Object.defineProperty(headers, key, {
71
+ value,
72
+ enumerable: true,
73
+ writable: true,
74
+ configurable: true,
75
+ });
76
+ });
77
+ const headersResult = await validateData(config, headers);
78
+ if (!headersResult.success) {
79
+ errors.push(...headersResult.errors);
80
+ }
81
+ else {
82
+ validatedData['headers'] = headersResult.data;
83
+ }
84
+ }
85
+ /**
86
+ * Helper function to validate unified input
87
+ * Merges body, query params, and URL params into a single object
88
+ * and validates against the input schema.
89
+ */
90
+ async function validateUnifiedInput(config, request, params, errors, validatedData) {
91
+ if (!config)
92
+ return false;
93
+ // Extract URL query parameters
94
+ const url = new URL(request.url);
95
+ const queryParams = Object.fromEntries(url.searchParams.entries());
96
+ // Extract request body (if not GET)
97
+ const body = request.method !== 'GET' ? await extractRequestBody(request) : {};
98
+ // Merge all inputs: query params + URL params + body
99
+ // Later values override earlier ones (body takes precedence)
100
+ const mergedInput = {
101
+ ...queryParams,
102
+ ...params,
103
+ ...(typeof body === 'object' && body !== null ? body : {}),
104
+ };
105
+ const inputResult = await validateData(config, mergedInput);
106
+ if (!inputResult.success) {
107
+ errors.push(...inputResult.errors);
108
+ }
109
+ else {
110
+ // Store validated data at top level for easy access
111
+ validatedData['input'] = inputResult.data;
112
+ // Also store in legacy locations for backwards compatibility
113
+ validatedData['body'] = inputResult.data;
114
+ validatedData['query'] = queryParams;
115
+ }
116
+ return true; // Indicates unified validation was performed
117
+ }
118
+ /**
119
+ * Create validation middleware for API routes
120
+ *
121
+ * Supports two validation modes:
122
+ * 1. Unified input validation (config.input): Merges body, query, and params
123
+ * into a single validated object. Preferred for new endpoints.
124
+ * 2. Legacy validation (config.body/query/headers): Validates each part
125
+ * separately. Maintained for backwards compatibility.
126
+ */
127
+ export function createValidationMiddleware(config) {
128
+ return async function validationMiddleware(request, _context, params) {
129
+ const errors = [];
130
+ const validatedData = {};
131
+ const routeParams = params !== null && params !== void 0 ? params : {};
132
+ try {
133
+ // Check for unified input validation first (preferred mode)
134
+ const usedUnifiedValidation = await validateUnifiedInput(config.input, request, routeParams, errors, validatedData);
135
+ // If unified validation was used, skip legacy body/query validation
136
+ // but still validate headers if configured
137
+ if (usedUnifiedValidation) {
138
+ await validateRequestHeaders(config.headers, request, errors, validatedData);
139
+ }
140
+ else {
141
+ // Fall back to legacy validation for separate body/query/headers
142
+ await validateRequestBody(config.body, request, errors, validatedData);
143
+ await validateRequestQuery(config.query, request, errors, validatedData);
144
+ await validateRequestHeaders(config.headers, request, errors, validatedData);
145
+ }
146
+ if (errors.length > 0) {
147
+ return NextResponse.json({
148
+ success: false,
149
+ error: 'Validation failed',
150
+ details: formatValidationErrors(errors),
151
+ timestamp: new Date().toISOString(),
152
+ }, { status: 400 });
153
+ }
154
+ return { validatedData };
155
+ }
156
+ catch (error) {
157
+ logger.error('Validation middleware error', {
158
+ error: error instanceof Error ? error.message : String(error),
159
+ });
160
+ return NextResponse.json({
161
+ success: false,
162
+ error: 'Validation error',
163
+ details: { server: ['Internal validation error'] },
164
+ timestamp: new Date().toISOString(),
165
+ }, { status: 500 });
166
+ }
167
+ };
168
+ }
169
+ /**
170
+ * Validation decorator for API route handlers
171
+ *
172
+ * Supports unified input validation when config.input is provided.
173
+ * Extracts route params from the context argument automatically.
174
+ */
175
+ export function validateRoute(config) {
176
+ return function (_target, _propertyKey, descriptor) {
177
+ const originalMethod = descriptor.value;
178
+ descriptor.value = async function (request, ...args) {
179
+ const middleware = createValidationMiddleware(config);
180
+ // Extract params from context (first arg after request in Next.js)
181
+ const context = args[0];
182
+ const params = extractParamsFromContext(context);
183
+ const result = await middleware(request, undefined, params);
184
+ // Check if result is an error response
185
+ if ('status' in result && result.status !== 200) {
186
+ return result;
187
+ }
188
+ // Add validated data to the request context
189
+ const validatedData = safeExtractValidatedData(result);
190
+ return originalMethod.call(this, request, validatedData, ...args);
191
+ };
192
+ return descriptor;
193
+ };
194
+ }
195
+ /**
196
+ * Extract route params from Next.js context
197
+ */
198
+ function extractParamsFromContext(context) {
199
+ if (typeof context !== 'object' || context === null)
200
+ return undefined;
201
+ const ctx = context;
202
+ if (typeof ctx['params'] !== 'object' || ctx['params'] === null) {
203
+ return undefined;
204
+ }
205
+ // Next.js params can be strings or arrays - normalize to strings
206
+ const params = ctx['params'];
207
+ const normalized = {};
208
+ // Use Object.entries to avoid object injection sink warnings
209
+ for (const [key, value] of Object.entries(params)) {
210
+ if (typeof value === 'string') {
211
+ Object.defineProperty(normalized, key, {
212
+ value,
213
+ enumerable: true,
214
+ writable: true,
215
+ configurable: true,
216
+ });
217
+ }
218
+ else if (Array.isArray(value) && value.length > 0) {
219
+ // For catch-all routes, join array segments
220
+ Object.defineProperty(normalized, key, {
221
+ value: value.join('/'),
222
+ enumerable: true,
223
+ writable: true,
224
+ configurable: true,
225
+ });
226
+ }
227
+ }
228
+ return normalized;
229
+ }
230
+ /**
231
+ * Higher-order function to wrap API route with validation
232
+ *
233
+ * Supports unified input validation when config.input is provided.
234
+ * Extracts route params from Next.js context automatically.
235
+ */
236
+ export function withValidation(config, handler) {
237
+ return async function (request, context) {
238
+ const middleware = createValidationMiddleware(config);
239
+ const params = extractParamsFromContext(context);
240
+ const result = await middleware(request, undefined, params);
241
+ // Check if result is an error response
242
+ if ('status' in result && result.status !== 200) {
243
+ return result;
244
+ }
245
+ const validatedData = safeExtractValidatedData(result);
246
+ return handler(request, validatedData, context);
247
+ };
248
+ }
249
+ /**
250
+ * Check if user agent indicates a bot
251
+ */
252
+ function isBotUserAgent(userAgent) {
253
+ return /bot|crawler|spider/i.test(userAgent);
254
+ }
255
+ /**
256
+ * Check if user agent indicates automated tools
257
+ */
258
+ function isAutomatedToolUserAgent(userAgent) {
259
+ return /bot|crawler|spider|curl|wget/i.test(userAgent);
260
+ }
261
+ /**
262
+ * Check if user agent indicates scripting languages
263
+ */
264
+ function isScriptingUserAgent(userAgent) {
265
+ return /bot|crawler|spider|curl|wget|python|ruby|php/i.test(userAgent);
266
+ }
267
+ /**
268
+ * Perform security checks based on level
269
+ */
270
+ function performSecurityCheck(securityLevel, userAgent, origin, hasAuthorization) {
271
+ switch (securityLevel) {
272
+ case SecurityLevel.LOW:
273
+ return true;
274
+ case SecurityLevel.MEDIUM:
275
+ return !isBotUserAgent(userAgent);
276
+ case SecurityLevel.HIGH:
277
+ return !isAutomatedToolUserAgent(userAgent) && origin.length > 0;
278
+ case SecurityLevel.CRITICAL:
279
+ return (!isScriptingUserAgent(userAgent) &&
280
+ origin.length > 0 &&
281
+ hasAuthorization);
282
+ default:
283
+ return false;
284
+ }
285
+ }
286
+ /**
287
+ * Security-focused validation middleware
288
+ */
289
+ export function createSecurityMiddleware(securityLevel = SecurityLevel.MEDIUM) {
290
+ return function (request) {
291
+ var _a, _b;
292
+ const userAgent = (_a = request.headers.get('user-agent')) !== null && _a !== void 0 ? _a : '';
293
+ const origin = (_b = request.headers.get('origin')) !== null && _b !== void 0 ? _b : '';
294
+ const hasAuthorization = request.headers.has('authorization');
295
+ const passes = performSecurityCheck(securityLevel, userAgent, origin, hasAuthorization);
296
+ if (!passes) {
297
+ return NextResponse.json({
298
+ success: false,
299
+ error: 'Security check failed',
300
+ timestamp: new Date().toISOString(),
301
+ }, { status: 403 });
302
+ }
303
+ return null; // Pass security check
304
+ };
305
+ }
306
+ /**
307
+ * Rate limiting middleware
308
+ *
309
+ * Uses standardized gateway MemoryRateLimitStore for consistent rate limiting across the application.
310
+ * This maintains backward compatibility with the existing Next.js API route middleware pattern
311
+ * while using the standardized gateway rate limiting infrastructure.
312
+ */
313
+ export function createRateLimitMiddleware(requests = 100, windowMs = 60000 // 1 minute
314
+ ) {
315
+ // Use the same store implementation as the gateway for consistency
316
+ const store = new MemoryRateLimitStore();
317
+ /**
318
+ * Extract client IP from request headers
319
+ */
320
+ function extractClientIP(request) {
321
+ var _a, _b;
322
+ return (((_b = (_a = request.headers.get('x-forwarded-for')) === null || _a === void 0 ? void 0 : _a.split(',')[0]) === null || _b === void 0 ? void 0 : _b.trim()) ||
323
+ request.headers.get('x-real-ip') ||
324
+ '127.0.0.1');
325
+ }
326
+ return function (request) {
327
+ const ip = extractClientIP(request);
328
+ const key = `rate-limit:ip:${ip}`;
329
+ const now = Date.now();
330
+ // Get current rate limit info
331
+ const info = store.get(key);
332
+ // Check if rate limit exceeded
333
+ if (info && info.count >= requests) {
334
+ const retryAfter = Math.max(0, Math.ceil((info.resetTime - now) / 1000));
335
+ return NextResponse.json({
336
+ success: false,
337
+ error: 'Rate limit exceeded',
338
+ retryAfter,
339
+ timestamp: new Date().toISOString(),
340
+ }, {
341
+ status: 429,
342
+ headers: {
343
+ 'X-RateLimit-Limit': requests.toString(),
344
+ 'X-RateLimit-Remaining': '0',
345
+ 'X-RateLimit-Reset': new Date(info.resetTime).toISOString(),
346
+ 'Retry-After': retryAfter.toString(),
347
+ },
348
+ });
349
+ }
350
+ // Increment the counter (this will create entry if it doesn't exist)
351
+ store.increment(key, windowMs);
352
+ // Return null to allow the request (rate limit passed)
353
+ return null;
354
+ };
355
+ }
356
+ /**
357
+ * Combine multiple middleware functions
358
+ */
359
+ export function combineMiddleware(...middlewares) {
360
+ return function (request) {
361
+ for (const middleware of middlewares) {
362
+ const result = middleware(request);
363
+ if (result) {
364
+ return result; // Return error response from first failing middleware
365
+ }
366
+ }
367
+ return null; // All middleware passed
368
+ };
369
+ }
370
+ /**
371
+ * Create comprehensive API middleware
372
+ *
373
+ * Supports unified input validation when options.validation.input is provided.
374
+ * Accepts optional context for extracting route params.
375
+ */
376
+ export function createApiMiddleware(options) {
377
+ const middlewares = [];
378
+ // Add security middleware
379
+ if (options.security) {
380
+ middlewares.push(createSecurityMiddleware(options.security));
381
+ }
382
+ // Add rate limiting
383
+ if (options.rateLimit) {
384
+ middlewares.push(createRateLimitMiddleware(options.rateLimit.requests, options.rateLimit.windowMs));
385
+ }
386
+ const combinedMiddleware = combineMiddleware(...middlewares);
387
+ return async function (request, handler, context) {
388
+ // Run security and rate limiting checks
389
+ const middlewareResult = combinedMiddleware(request);
390
+ if (middlewareResult) {
391
+ return middlewareResult;
392
+ }
393
+ // Run validation if configured
394
+ if (options.validation) {
395
+ const validationMiddleware = createValidationMiddleware(options.validation);
396
+ const params = extractParamsFromContext(context);
397
+ const validationResult = await validationMiddleware(request, undefined, params);
398
+ if ('status' in validationResult && validationResult.status !== 200) {
399
+ return validationResult;
400
+ }
401
+ const validatedData = safeExtractValidatedData(validationResult);
402
+ return handler(request, validatedData);
403
+ }
404
+ return handler(request);
405
+ };
406
+ }
407
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * String Sanitization Utilities
3
+ *
4
+ * Centralized XSS/SQL injection protection and string sanitization.
5
+ * This is the single source of truth for sanitization patterns.
6
+ */
7
+ import type { SanitizationOptions } from './types';
8
+ /**
9
+ * XSS detection patterns
10
+ */
11
+ export declare const XSS_PATTERNS: {
12
+ readonly scriptTags: RegExp;
13
+ readonly iframeTags: RegExp;
14
+ readonly javascriptProtocol: RegExp;
15
+ readonly vbscriptProtocol: RegExp;
16
+ readonly eventHandlers: RegExp;
17
+ };
18
+ /**
19
+ * SQL injection patterns
20
+ */
21
+ export declare const SQL_PATTERNS: {
22
+ readonly specialChars: RegExp;
23
+ readonly keywords: RegExp;
24
+ };
25
+ /**
26
+ * HTML entity mapping for encoding
27
+ */
28
+ export declare const HTML_ENTITIES: Record<string, string>;
29
+ /**
30
+ * Check if a string contains XSS patterns (for validation without modification)
31
+ */
32
+ export declare function containsXssPatterns(value: string): boolean;
33
+ /**
34
+ * Sanitize string input by removing/encoding dangerous patterns
35
+ */
36
+ export declare function sanitizeString(input: string, options?: SanitizationOptions): string;
37
+ /**
38
+ * Recursively sanitize string fields in an object
39
+ */
40
+ export declare function sanitizeObjectStrings(obj: unknown): unknown;
41
+ //# sourceMappingURL=sanitization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitization.d.ts","sourceRoot":"","sources":["../sanitization.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,MAAM,CA0CR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA8B3D"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * String Sanitization Utilities
3
+ *
4
+ * Centralized XSS/SQL injection protection and string sanitization.
5
+ * This is the single source of truth for sanitization patterns.
6
+ */
7
+ /**
8
+ * XSS detection patterns
9
+ */
10
+ export const XSS_PATTERNS = {
11
+ scriptTags: /<script[^>]*>.*?<\/script>/gi,
12
+ iframeTags: /<iframe[^>]*>.*?<\/iframe>/gi,
13
+ javascriptProtocol: /javascript:/gi,
14
+ vbscriptProtocol: /vbscript:/gi,
15
+ eventHandlers: /on\w+=/gi,
16
+ };
17
+ /**
18
+ * SQL injection patterns
19
+ */
20
+ export const SQL_PATTERNS = {
21
+ specialChars: /['";\\]/g,
22
+ keywords: /\b(union|select|insert|update|delete|drop|exec|execute)\b/gi,
23
+ };
24
+ /**
25
+ * HTML entity mapping for encoding
26
+ */
27
+ export const HTML_ENTITIES = {
28
+ '&': '&amp;',
29
+ '<': '&lt;',
30
+ '>': '&gt;',
31
+ '"': '&quot;',
32
+ "'": '&#x27;',
33
+ };
34
+ /**
35
+ * Check if a string contains XSS patterns (for validation without modification)
36
+ */
37
+ export function containsXssPatterns(value) {
38
+ const hasScriptTag = /<script/i.test(value);
39
+ const hasEventHandler = /on\w+=/i.test(value);
40
+ const hasJavascriptProtocol = /javascript:/i.test(value);
41
+ return hasScriptTag || hasEventHandler || hasJavascriptProtocol;
42
+ }
43
+ /**
44
+ * Sanitize string input by removing/encoding dangerous patterns
45
+ */
46
+ export function sanitizeString(input, options = {}) {
47
+ let sanitized = input;
48
+ // Trim whitespace
49
+ if (options.trim !== false) {
50
+ sanitized = sanitized.trim();
51
+ }
52
+ // XSS protection
53
+ if (options.xss !== false) {
54
+ sanitized = sanitized
55
+ .replace(XSS_PATTERNS.scriptTags, '')
56
+ .replace(XSS_PATTERNS.iframeTags, '')
57
+ .replace(XSS_PATTERNS.javascriptProtocol, '')
58
+ .replace(XSS_PATTERNS.vbscriptProtocol, '')
59
+ .replace(XSS_PATTERNS.eventHandlers, '');
60
+ }
61
+ // SQL injection protection
62
+ if (options.sql !== false) {
63
+ sanitized = sanitized
64
+ .replace(SQL_PATTERNS.specialChars, '')
65
+ .replace(SQL_PATTERNS.keywords, '');
66
+ }
67
+ // HTML encoding
68
+ if (options.html) {
69
+ sanitized = sanitized.replace(/[&<>"']/g,
70
+ // eslint-disable-next-line security/detect-object-injection -- char is from known regex match set
71
+ (char) => { var _a; return (_a = HTML_ENTITIES[char]) !== null && _a !== void 0 ? _a : char; });
72
+ }
73
+ // Case transformations
74
+ if (options.lowercase) {
75
+ sanitized = sanitized.toLowerCase();
76
+ }
77
+ else if (options.uppercase) {
78
+ sanitized = sanitized.toUpperCase();
79
+ }
80
+ return sanitized;
81
+ }
82
+ /**
83
+ * Recursively sanitize string fields in an object
84
+ */
85
+ export function sanitizeObjectStrings(obj) {
86
+ if (typeof obj === 'string') {
87
+ return sanitizeString(obj, { xss: true, sql: true, trim: true });
88
+ }
89
+ if (Array.isArray(obj)) {
90
+ return obj.map(sanitizeObjectStrings);
91
+ }
92
+ if (typeof obj === 'object' && obj !== null) {
93
+ const sanitized = {};
94
+ for (const [key, value] of Object.entries(obj)) {
95
+ // Type-safe property assignment for security
96
+ if (typeof key === 'string' &&
97
+ Object.prototype.hasOwnProperty.call(obj, key)) {
98
+ // Use Object.defineProperty to safely assign dynamic keys
99
+ Object.defineProperty(sanitized, key, {
100
+ value: sanitizeObjectStrings(value),
101
+ writable: true,
102
+ enumerable: true,
103
+ configurable: true,
104
+ });
105
+ }
106
+ }
107
+ return sanitized;
108
+ }
109
+ return obj;
110
+ }
111
+ //# sourceMappingURL=sanitization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitization.js","sourceRoot":"","sources":["../sanitization.ts"],"names":[],"mappings":"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"}