@arcis/node 1.3.0 → 1.4.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.
Files changed (118) hide show
  1. package/dist/core/{index.d.mts → constants.d.ts} +21 -70
  2. package/dist/core/constants.d.ts.map +1 -0
  3. package/dist/core/errors.d.ts +53 -0
  4. package/dist/core/errors.d.ts.map +1 -0
  5. package/dist/core/index.d.ts +6 -168
  6. package/dist/core/index.d.ts.map +1 -0
  7. package/dist/{types-BOkx5YJc.d.mts → core/types.d.ts} +27 -30
  8. package/dist/core/types.d.ts.map +1 -0
  9. package/dist/index.d.ts +71 -166
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +57 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +56 -3
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/logging/index.d.ts +4 -36
  16. package/dist/logging/index.d.ts.map +1 -0
  17. package/dist/logging/{index.d.mts → redactor.d.ts} +5 -9
  18. package/dist/logging/redactor.d.ts.map +1 -0
  19. package/dist/middleware/bot-detection.d.ts +86 -0
  20. package/dist/middleware/bot-detection.d.ts.map +1 -0
  21. package/dist/middleware/cookies.d.ts +48 -0
  22. package/dist/middleware/cookies.d.ts.map +1 -0
  23. package/dist/middleware/cors.d.ts +65 -0
  24. package/dist/middleware/cors.d.ts.map +1 -0
  25. package/dist/middleware/csrf.d.ts +109 -0
  26. package/dist/middleware/csrf.d.ts.map +1 -0
  27. package/dist/middleware/error-handler.d.ts +43 -0
  28. package/dist/middleware/error-handler.d.ts.map +1 -0
  29. package/dist/middleware/headers.d.ts +29 -0
  30. package/dist/middleware/headers.d.ts.map +1 -0
  31. package/dist/middleware/hpp.d.ts +56 -0
  32. package/dist/middleware/hpp.d.ts.map +1 -0
  33. package/dist/middleware/index.d.ts +16 -3
  34. package/dist/middleware/index.d.ts.map +1 -0
  35. package/dist/middleware/index.js +6 -1
  36. package/dist/middleware/index.js.map +1 -1
  37. package/dist/middleware/index.mjs +6 -1
  38. package/dist/middleware/index.mjs.map +1 -1
  39. package/dist/middleware/main.d.ts +40 -0
  40. package/dist/middleware/main.d.ts.map +1 -0
  41. package/dist/middleware/rate-limit-sliding.d.ts +46 -0
  42. package/dist/middleware/rate-limit-sliding.d.ts.map +1 -0
  43. package/dist/middleware/rate-limit-token.d.ts +51 -0
  44. package/dist/middleware/rate-limit-token.d.ts.map +1 -0
  45. package/dist/middleware/rate-limit.d.ts +34 -0
  46. package/dist/middleware/rate-limit.d.ts.map +1 -0
  47. package/dist/sanitizers/command.d.ts +28 -0
  48. package/dist/sanitizers/command.d.ts.map +1 -0
  49. package/dist/sanitizers/encode.d.ts +46 -0
  50. package/dist/sanitizers/encode.d.ts.map +1 -0
  51. package/dist/sanitizers/headers.d.ts +46 -0
  52. package/dist/sanitizers/headers.d.ts.map +1 -0
  53. package/dist/sanitizers/index.d.ts +17 -22
  54. package/dist/sanitizers/index.d.ts.map +1 -0
  55. package/dist/sanitizers/jsonp.d.ts +34 -0
  56. package/dist/sanitizers/jsonp.d.ts.map +1 -0
  57. package/dist/sanitizers/nosql.d.ts +31 -0
  58. package/dist/sanitizers/nosql.d.ts.map +1 -0
  59. package/dist/sanitizers/path.d.ts +28 -0
  60. package/dist/sanitizers/path.d.ts.map +1 -0
  61. package/dist/sanitizers/pii.d.ts +80 -0
  62. package/dist/sanitizers/pii.d.ts.map +1 -0
  63. package/dist/sanitizers/prototype.d.ts +34 -0
  64. package/dist/sanitizers/prototype.d.ts.map +1 -0
  65. package/dist/sanitizers/sanitize.d.ts +51 -0
  66. package/dist/sanitizers/sanitize.d.ts.map +1 -0
  67. package/dist/sanitizers/sql.d.ts +28 -0
  68. package/dist/sanitizers/sql.d.ts.map +1 -0
  69. package/dist/sanitizers/ssti.d.ts +20 -0
  70. package/dist/sanitizers/ssti.d.ts.map +1 -0
  71. package/dist/sanitizers/utils.d.ts +19 -0
  72. package/dist/sanitizers/utils.d.ts.map +1 -0
  73. package/dist/sanitizers/xss.d.ts +35 -0
  74. package/dist/sanitizers/xss.d.ts.map +1 -0
  75. package/dist/sanitizers/xxe.d.ts +20 -0
  76. package/dist/sanitizers/xxe.d.ts.map +1 -0
  77. package/dist/stores/index.d.ts +6 -104
  78. package/dist/stores/index.d.ts.map +1 -0
  79. package/dist/stores/memory.d.ts +35 -0
  80. package/dist/stores/memory.d.ts.map +1 -0
  81. package/dist/stores/{index.d.mts → redis.d.ts} +6 -45
  82. package/dist/stores/redis.d.ts.map +1 -0
  83. package/dist/utils/duration.d.ts +34 -0
  84. package/dist/utils/duration.d.ts.map +1 -0
  85. package/dist/utils/fingerprint.d.ts +64 -0
  86. package/dist/utils/fingerprint.d.ts.map +1 -0
  87. package/dist/utils/index.d.ts +10 -0
  88. package/dist/utils/index.d.ts.map +1 -0
  89. package/dist/utils/index.js +188 -0
  90. package/dist/utils/index.js.map +1 -0
  91. package/dist/utils/index.mjs +182 -0
  92. package/dist/utils/index.mjs.map +1 -0
  93. package/dist/utils/ip.d.ts +70 -0
  94. package/dist/utils/ip.d.ts.map +1 -0
  95. package/dist/validation/email.d.ts +82 -0
  96. package/dist/validation/email.d.ts.map +1 -0
  97. package/dist/validation/file.d.ts +90 -0
  98. package/dist/validation/file.d.ts.map +1 -0
  99. package/dist/validation/index.d.ts +10 -3
  100. package/dist/validation/index.d.ts.map +1 -0
  101. package/dist/validation/redirect.d.ts +64 -0
  102. package/dist/validation/redirect.d.ts.map +1 -0
  103. package/dist/validation/schema.d.ts +36 -0
  104. package/dist/validation/schema.d.ts.map +1 -0
  105. package/dist/validation/url.d.ts +65 -0
  106. package/dist/validation/url.d.ts.map +1 -0
  107. package/package.json +8 -6
  108. package/dist/encode-CrQCGlBq.d.mts +0 -484
  109. package/dist/encode-jl9sOwmA.d.ts +0 -484
  110. package/dist/index-BAhgn9V2.d.ts +0 -532
  111. package/dist/index-BGNKspqH.d.ts +0 -340
  112. package/dist/index-Cd02z-0j.d.mts +0 -340
  113. package/dist/index-DgJtWMSj.d.mts +0 -532
  114. package/dist/index.d.mts +0 -175
  115. package/dist/middleware/index.d.mts +0 -3
  116. package/dist/sanitizers/index.d.mts +0 -24
  117. package/dist/types-BOkx5YJc.d.ts +0 -279
  118. package/dist/validation/index.d.mts +0 -3
@@ -1,340 +0,0 @@
1
- import { RequestHandler } from 'express';
2
- import { n as ValidationSchema } from './types-BOkx5YJc.js';
3
-
4
- /**
5
- * @module @arcis/node/validation/schema
6
- * Request validation middleware
7
- */
8
-
9
- /**
10
- * Create Express middleware for request validation.
11
- * Prevents mass assignment by only allowing fields defined in the schema.
12
- *
13
- * @param schema - Validation schema defining expected fields
14
- * @param source - Request property to validate ('body', 'query', or 'params')
15
- * @returns Express middleware
16
- *
17
- * @example
18
- * app.post('/users', validate({
19
- * email: { type: 'email', required: true },
20
- * name: { type: 'string', min: 2, max: 50 },
21
- * age: { type: 'number', min: 0, max: 150 },
22
- * role: { type: 'string', enum: ['user', 'admin'] }
23
- * }), handler);
24
- *
25
- * @example
26
- * // Validate query params
27
- * app.get('/search', validate({
28
- * q: { type: 'string', required: true, min: 1 },
29
- * page: { type: 'number', min: 1 }
30
- * }, 'query'), handler);
31
- */
32
- declare function validate(schema: ValidationSchema, source?: 'body' | 'query' | 'params'): RequestHandler;
33
- /**
34
- * Alias for validate
35
- * @see validate
36
- */
37
- declare const createValidator: typeof validate;
38
-
39
- /**
40
- * @module @arcis/node/validation/url
41
- * SSRF (Server-Side Request Forgery) prevention
42
- *
43
- * Validates URLs to ensure they don't target private/internal networks,
44
- * localhost, cloud metadata endpoints, or use dangerous protocols.
45
- *
46
- * @example
47
- * import { validateUrl } from '@arcis/node';
48
- *
49
- * // Block SSRF attempts
50
- * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' }
51
- * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' }
52
- * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' }
53
- * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' }
54
- *
55
- * // Allow safe URLs
56
- * validateUrl('https://api.example.com/data') // { safe: true }
57
- */
58
- /** Options for URL validation */
59
- interface ValidateUrlOptions {
60
- /** Allowed protocols. Default: ['http:', 'https:'] */
61
- allowedProtocols?: string[];
62
- /** Additional hostnames to block (e.g., internal service names) */
63
- blockedHosts?: string[];
64
- /** Additional hostnames to always allow (bypass IP checks) */
65
- allowedHosts?: string[];
66
- /** Allow localhost/loopback. Default: false */
67
- allowLocalhost?: boolean;
68
- /** Allow private/internal IPs. Default: false */
69
- allowPrivate?: boolean;
70
- }
71
- /** Result of URL validation */
72
- interface ValidateUrlResult {
73
- /** Whether the URL is safe to fetch */
74
- safe: boolean;
75
- /** Reason the URL was blocked (only set when safe=false) */
76
- reason?: string;
77
- }
78
- /**
79
- * Validate a URL for SSRF safety.
80
- *
81
- * Checks:
82
- * 1. Valid URL format
83
- * 2. Allowed protocol (default: http, https only)
84
- * 3. Not localhost/loopback (127.x.x.x, ::1, localhost)
85
- * 4. Not private IP (10.x, 172.16-31.x, 192.168.x)
86
- * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata)
87
- * 6. Not blocked hostname
88
- * 7. No credentials in URL (user:pass@host)
89
- *
90
- * @param url - The URL string to validate
91
- * @param options - Validation options
92
- * @returns Validation result with safe flag and optional reason
93
- */
94
- declare function validateUrl(url: string, options?: ValidateUrlOptions): ValidateUrlResult;
95
- /**
96
- * Convenience wrapper that returns true/false.
97
- *
98
- * @param url - The URL to check
99
- * @param options - Validation options
100
- * @returns true if the URL is safe to fetch
101
- */
102
- declare function isUrlSafe(url: string, options?: ValidateUrlOptions): boolean;
103
-
104
- /**
105
- * @module @arcis/node/validation/redirect
106
- * Open Redirect prevention
107
- *
108
- * Prevents attackers from using your app to redirect users to malicious sites
109
- * via manipulated query parameters like ?returnUrl=http://evil.com
110
- *
111
- * @example
112
- * import { validateRedirect, isRedirectSafe } from '@arcis/node';
113
- *
114
- * // Block open redirects
115
- * validateRedirect('http://evil.com') // { safe: false, reason: 'absolute URL not in allowed hosts' }
116
- * validateRedirect('//evil.com') // { safe: false, reason: 'protocol-relative URL not in allowed hosts' }
117
- * validateRedirect('javascript:alert(1)') // { safe: false, reason: 'dangerous protocol: javascript:' }
118
- *
119
- * // Allow safe redirects
120
- * validateRedirect('/dashboard') // { safe: true }
121
- * validateRedirect('/users?page=2') // { safe: true }
122
- * validateRedirect('https://myapp.com/home', { allowedHosts: ['myapp.com'] }) // { safe: true }
123
- */
124
- /** Options for redirect validation */
125
- interface ValidateRedirectOptions {
126
- /** Hostnames that are allowed for absolute URL redirects */
127
- allowedHosts?: string[];
128
- /** Allow protocol-relative URLs (//example.com). Default: false */
129
- allowProtocolRelative?: boolean;
130
- /** Allowed protocols for absolute URLs. Default: ['http:', 'https:'] */
131
- allowedProtocols?: string[];
132
- }
133
- /** Result of redirect validation */
134
- interface ValidateRedirectResult {
135
- /** Whether the redirect URL is safe */
136
- safe: boolean;
137
- /** Reason the redirect was blocked (only set when safe=false) */
138
- reason?: string;
139
- }
140
- /**
141
- * Validate a redirect URL to prevent open redirect attacks.
142
- *
143
- * Safe redirects:
144
- * - Relative paths: /dashboard, /users?page=2, ../settings
145
- * - Absolute URLs to allowed hosts (when configured)
146
- *
147
- * Blocked redirects:
148
- * - Absolute URLs to unknown hosts
149
- * - Protocol-relative URLs (//evil.com)
150
- * - javascript:, data:, vbscript:, blob: protocols
151
- * - Backslash-prefixed paths (\\evil.com — browser treats as //)
152
- * - URLs with control characters that could disguise the target
153
- *
154
- * @param url - The redirect target URL to validate
155
- * @param options - Validation options
156
- * @returns Validation result with safe flag and optional reason
157
- */
158
- declare function validateRedirect(url: string, options?: ValidateRedirectOptions): ValidateRedirectResult;
159
- /**
160
- * Convenience wrapper that returns true/false.
161
- *
162
- * @param url - The redirect URL to check
163
- * @param options - Validation options
164
- * @returns true if the redirect is safe
165
- */
166
- declare function isRedirectSafe(url: string, options?: ValidateRedirectOptions): boolean;
167
-
168
- /**
169
- * @module @arcis/node/validation/file
170
- * File upload validation and filename sanitization
171
- */
172
- /** File upload validation options */
173
- interface ValidateFileOptions {
174
- /** Maximum file size in bytes. Default: 5MB */
175
- maxSize?: number;
176
- /** Allowed MIME types (e.g., ['image/jpeg', 'image/png']) */
177
- allowedTypes?: string[];
178
- /** Allowed file extensions (e.g., ['.jpg', '.png']). Includes dot. */
179
- allowedExtensions?: string[];
180
- /** Block dangerous/executable extensions. Default: true */
181
- blockExecutables?: boolean;
182
- /** Validate magic bytes match the claimed MIME type. Default: true */
183
- validateMagicBytes?: boolean;
184
- /** Block files with no extension. Default: true */
185
- blockNoExtension?: boolean;
186
- /** Block double extensions (e.g., file.php.jpg). Default: true */
187
- blockDoubleExtensions?: boolean;
188
- }
189
- /** File metadata for validation */
190
- interface FileInput {
191
- /** Original filename */
192
- filename: string;
193
- /** MIME type (as claimed by client) */
194
- mimetype: string;
195
- /** File size in bytes */
196
- size: number;
197
- /** File content buffer (for magic byte validation) */
198
- buffer?: Buffer;
199
- }
200
- /** File validation result */
201
- interface ValidateFileResult {
202
- /** Whether the file passed validation */
203
- valid: boolean;
204
- /** Validation errors (empty if valid) */
205
- errors: string[];
206
- /** Sanitized filename (safe for storage) */
207
- sanitizedFilename: string;
208
- }
209
- /**
210
- * Sanitize a filename for safe storage.
211
- *
212
- * Strips path traversal, null bytes, control characters, and special characters.
213
- * Preserves the extension and converts to a filesystem-safe name.
214
- *
215
- * @param filename - The original filename
216
- * @returns A sanitized filename safe for storage
217
- *
218
- * @example
219
- * sanitizeFilename('../../etc/passwd') // 'etc_passwd'
220
- * sanitizeFilename('file<name>.jpg') // 'filename.jpg'
221
- * sanitizeFilename('photo (1).jpg') // 'photo_1.jpg'
222
- * sanitizeFilename('.htaccess') // 'htaccess'
223
- */
224
- declare function sanitizeFilename(filename: string): string;
225
- /**
226
- * Validate a file upload for security.
227
- *
228
- * Checks file size, MIME type, extension, magic bytes, and dangerous patterns.
229
- * Returns a result with validation errors and a sanitized filename.
230
- *
231
- * @param file - File metadata and optional content
232
- * @param options - Validation options
233
- * @returns Validation result
234
- *
235
- * @example
236
- * const result = validateFile(
237
- * { filename: 'photo.jpg', mimetype: 'image/jpeg', size: 1024, buffer },
238
- * { allowedTypes: ['image/jpeg', 'image/png'], maxSize: 2 * 1024 * 1024 }
239
- * );
240
- * if (!result.valid) {
241
- * return res.status(400).json({ errors: result.errors });
242
- * }
243
- * // Use result.sanitizedFilename for storage
244
- *
245
- * @example
246
- * // Block executables only (no whitelist)
247
- * const result = validateFile(file, { blockExecutables: true });
248
- */
249
- declare function validateFile(file: FileInput, options?: ValidateFileOptions): ValidateFileResult;
250
- /**
251
- * Check if a file extension is considered dangerous/executable.
252
- *
253
- * @param filename - Filename or extension to check
254
- * @returns true if the extension is dangerous
255
- */
256
- declare function isDangerousExtension(filename: string): boolean;
257
-
258
- /**
259
- * @module @arcis/node/validation/email
260
- * Advanced email validation with disposable detection and typo suggestions.
261
- *
262
- * Three levels of validation:
263
- * 1. Syntax — RFC-compliant format checking
264
- * 2. Domain intelligence — disposable/free provider detection, typo correction
265
- * 3. MX verification — DNS MX record lookup (async, optional)
266
- *
267
- * @example
268
- * const result = validateEmail('user@tempmail.com');
269
- * // { valid: false, reason: 'disposable' }
270
- *
271
- * const result = validateEmail('user@gmial.com');
272
- * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }
273
- */
274
- interface EmailValidationOptions {
275
- /** Check for disposable email providers. Default: true */
276
- checkDisposable?: boolean;
277
- /** Suggest corrections for typos. Default: true */
278
- suggestTypoFix?: boolean;
279
- /** Verify MX records via DNS. Default: false */
280
- checkMx?: boolean;
281
- /** Additional blocked domains */
282
- blockedDomains?: string[];
283
- /** Additional allowed domains (bypasses disposable check) */
284
- allowedDomains?: string[];
285
- }
286
- interface EmailValidationResult {
287
- /** Whether the email is valid */
288
- valid: boolean;
289
- /** Reason for the result */
290
- reason: 'valid' | 'invalid_syntax' | 'disposable' | 'no_mx' | 'blocked' | 'typo';
291
- /** Suggested correction if a typo was detected */
292
- suggestion: string | null;
293
- /** Whether the domain is a free email provider */
294
- isFree: boolean;
295
- /** Whether the domain is a disposable email provider */
296
- isDisposable: boolean;
297
- /** The normalized email address */
298
- normalized: string;
299
- }
300
- /**
301
- * Validate an email address with syntax checking, disposable detection,
302
- * and typo suggestions.
303
- *
304
- * @param email - Email address to validate
305
- * @param options - Validation options
306
- * @returns Validation result
307
- *
308
- * @example
309
- * validateEmail('user@gmail.com')
310
- * // { valid: true, reason: 'valid', isFree: true }
311
- *
312
- * validateEmail('user@tempmail.com')
313
- * // { valid: false, reason: 'disposable' }
314
- *
315
- * validateEmail('user@gmial.com')
316
- * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }
317
- */
318
- declare function validateEmail(email: string, options?: EmailValidationOptions): EmailValidationResult;
319
- /**
320
- * Verify that the email domain has MX records (can receive email).
321
- *
322
- * This performs a DNS lookup and requires network access.
323
- * Use for registration flows where you need high confidence.
324
- *
325
- * @param email - Email address to verify
326
- * @returns True if the domain has MX records
327
- *
328
- * @example
329
- * if (await verifyEmailMx('user@example.com')) {
330
- * // Domain can receive email
331
- * }
332
- */
333
- declare function verifyEmailMx(email: string): Promise<boolean>;
334
- /**
335
- * Quick check if an email address has valid syntax.
336
- * Faster than validateEmail() — just syntax, no domain intelligence.
337
- */
338
- declare function isValidEmailSyntax(email: string): boolean;
339
-
340
- export { type EmailValidationOptions as E, type FileInput as F, type ValidateFileOptions as V, type EmailValidationResult as a, type ValidateFileResult as b, type ValidateRedirectOptions as c, type ValidateRedirectResult as d, type ValidateUrlOptions as e, type ValidateUrlResult as f, createValidator as g, isRedirectSafe as h, isDangerousExtension as i, isUrlSafe as j, isValidEmailSyntax as k, validateEmail as l, validateFile as m, validateRedirect as n, validateUrl as o, verifyEmailMx as p, sanitizeFilename as s, validate as v };
@@ -1,340 +0,0 @@
1
- import { RequestHandler } from 'express';
2
- import { n as ValidationSchema } from './types-BOkx5YJc.mjs';
3
-
4
- /**
5
- * @module @arcis/node/validation/schema
6
- * Request validation middleware
7
- */
8
-
9
- /**
10
- * Create Express middleware for request validation.
11
- * Prevents mass assignment by only allowing fields defined in the schema.
12
- *
13
- * @param schema - Validation schema defining expected fields
14
- * @param source - Request property to validate ('body', 'query', or 'params')
15
- * @returns Express middleware
16
- *
17
- * @example
18
- * app.post('/users', validate({
19
- * email: { type: 'email', required: true },
20
- * name: { type: 'string', min: 2, max: 50 },
21
- * age: { type: 'number', min: 0, max: 150 },
22
- * role: { type: 'string', enum: ['user', 'admin'] }
23
- * }), handler);
24
- *
25
- * @example
26
- * // Validate query params
27
- * app.get('/search', validate({
28
- * q: { type: 'string', required: true, min: 1 },
29
- * page: { type: 'number', min: 1 }
30
- * }, 'query'), handler);
31
- */
32
- declare function validate(schema: ValidationSchema, source?: 'body' | 'query' | 'params'): RequestHandler;
33
- /**
34
- * Alias for validate
35
- * @see validate
36
- */
37
- declare const createValidator: typeof validate;
38
-
39
- /**
40
- * @module @arcis/node/validation/url
41
- * SSRF (Server-Side Request Forgery) prevention
42
- *
43
- * Validates URLs to ensure they don't target private/internal networks,
44
- * localhost, cloud metadata endpoints, or use dangerous protocols.
45
- *
46
- * @example
47
- * import { validateUrl } from '@arcis/node';
48
- *
49
- * // Block SSRF attempts
50
- * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' }
51
- * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' }
52
- * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' }
53
- * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' }
54
- *
55
- * // Allow safe URLs
56
- * validateUrl('https://api.example.com/data') // { safe: true }
57
- */
58
- /** Options for URL validation */
59
- interface ValidateUrlOptions {
60
- /** Allowed protocols. Default: ['http:', 'https:'] */
61
- allowedProtocols?: string[];
62
- /** Additional hostnames to block (e.g., internal service names) */
63
- blockedHosts?: string[];
64
- /** Additional hostnames to always allow (bypass IP checks) */
65
- allowedHosts?: string[];
66
- /** Allow localhost/loopback. Default: false */
67
- allowLocalhost?: boolean;
68
- /** Allow private/internal IPs. Default: false */
69
- allowPrivate?: boolean;
70
- }
71
- /** Result of URL validation */
72
- interface ValidateUrlResult {
73
- /** Whether the URL is safe to fetch */
74
- safe: boolean;
75
- /** Reason the URL was blocked (only set when safe=false) */
76
- reason?: string;
77
- }
78
- /**
79
- * Validate a URL for SSRF safety.
80
- *
81
- * Checks:
82
- * 1. Valid URL format
83
- * 2. Allowed protocol (default: http, https only)
84
- * 3. Not localhost/loopback (127.x.x.x, ::1, localhost)
85
- * 4. Not private IP (10.x, 172.16-31.x, 192.168.x)
86
- * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata)
87
- * 6. Not blocked hostname
88
- * 7. No credentials in URL (user:pass@host)
89
- *
90
- * @param url - The URL string to validate
91
- * @param options - Validation options
92
- * @returns Validation result with safe flag and optional reason
93
- */
94
- declare function validateUrl(url: string, options?: ValidateUrlOptions): ValidateUrlResult;
95
- /**
96
- * Convenience wrapper that returns true/false.
97
- *
98
- * @param url - The URL to check
99
- * @param options - Validation options
100
- * @returns true if the URL is safe to fetch
101
- */
102
- declare function isUrlSafe(url: string, options?: ValidateUrlOptions): boolean;
103
-
104
- /**
105
- * @module @arcis/node/validation/redirect
106
- * Open Redirect prevention
107
- *
108
- * Prevents attackers from using your app to redirect users to malicious sites
109
- * via manipulated query parameters like ?returnUrl=http://evil.com
110
- *
111
- * @example
112
- * import { validateRedirect, isRedirectSafe } from '@arcis/node';
113
- *
114
- * // Block open redirects
115
- * validateRedirect('http://evil.com') // { safe: false, reason: 'absolute URL not in allowed hosts' }
116
- * validateRedirect('//evil.com') // { safe: false, reason: 'protocol-relative URL not in allowed hosts' }
117
- * validateRedirect('javascript:alert(1)') // { safe: false, reason: 'dangerous protocol: javascript:' }
118
- *
119
- * // Allow safe redirects
120
- * validateRedirect('/dashboard') // { safe: true }
121
- * validateRedirect('/users?page=2') // { safe: true }
122
- * validateRedirect('https://myapp.com/home', { allowedHosts: ['myapp.com'] }) // { safe: true }
123
- */
124
- /** Options for redirect validation */
125
- interface ValidateRedirectOptions {
126
- /** Hostnames that are allowed for absolute URL redirects */
127
- allowedHosts?: string[];
128
- /** Allow protocol-relative URLs (//example.com). Default: false */
129
- allowProtocolRelative?: boolean;
130
- /** Allowed protocols for absolute URLs. Default: ['http:', 'https:'] */
131
- allowedProtocols?: string[];
132
- }
133
- /** Result of redirect validation */
134
- interface ValidateRedirectResult {
135
- /** Whether the redirect URL is safe */
136
- safe: boolean;
137
- /** Reason the redirect was blocked (only set when safe=false) */
138
- reason?: string;
139
- }
140
- /**
141
- * Validate a redirect URL to prevent open redirect attacks.
142
- *
143
- * Safe redirects:
144
- * - Relative paths: /dashboard, /users?page=2, ../settings
145
- * - Absolute URLs to allowed hosts (when configured)
146
- *
147
- * Blocked redirects:
148
- * - Absolute URLs to unknown hosts
149
- * - Protocol-relative URLs (//evil.com)
150
- * - javascript:, data:, vbscript:, blob: protocols
151
- * - Backslash-prefixed paths (\\evil.com — browser treats as //)
152
- * - URLs with control characters that could disguise the target
153
- *
154
- * @param url - The redirect target URL to validate
155
- * @param options - Validation options
156
- * @returns Validation result with safe flag and optional reason
157
- */
158
- declare function validateRedirect(url: string, options?: ValidateRedirectOptions): ValidateRedirectResult;
159
- /**
160
- * Convenience wrapper that returns true/false.
161
- *
162
- * @param url - The redirect URL to check
163
- * @param options - Validation options
164
- * @returns true if the redirect is safe
165
- */
166
- declare function isRedirectSafe(url: string, options?: ValidateRedirectOptions): boolean;
167
-
168
- /**
169
- * @module @arcis/node/validation/file
170
- * File upload validation and filename sanitization
171
- */
172
- /** File upload validation options */
173
- interface ValidateFileOptions {
174
- /** Maximum file size in bytes. Default: 5MB */
175
- maxSize?: number;
176
- /** Allowed MIME types (e.g., ['image/jpeg', 'image/png']) */
177
- allowedTypes?: string[];
178
- /** Allowed file extensions (e.g., ['.jpg', '.png']). Includes dot. */
179
- allowedExtensions?: string[];
180
- /** Block dangerous/executable extensions. Default: true */
181
- blockExecutables?: boolean;
182
- /** Validate magic bytes match the claimed MIME type. Default: true */
183
- validateMagicBytes?: boolean;
184
- /** Block files with no extension. Default: true */
185
- blockNoExtension?: boolean;
186
- /** Block double extensions (e.g., file.php.jpg). Default: true */
187
- blockDoubleExtensions?: boolean;
188
- }
189
- /** File metadata for validation */
190
- interface FileInput {
191
- /** Original filename */
192
- filename: string;
193
- /** MIME type (as claimed by client) */
194
- mimetype: string;
195
- /** File size in bytes */
196
- size: number;
197
- /** File content buffer (for magic byte validation) */
198
- buffer?: Buffer;
199
- }
200
- /** File validation result */
201
- interface ValidateFileResult {
202
- /** Whether the file passed validation */
203
- valid: boolean;
204
- /** Validation errors (empty if valid) */
205
- errors: string[];
206
- /** Sanitized filename (safe for storage) */
207
- sanitizedFilename: string;
208
- }
209
- /**
210
- * Sanitize a filename for safe storage.
211
- *
212
- * Strips path traversal, null bytes, control characters, and special characters.
213
- * Preserves the extension and converts to a filesystem-safe name.
214
- *
215
- * @param filename - The original filename
216
- * @returns A sanitized filename safe for storage
217
- *
218
- * @example
219
- * sanitizeFilename('../../etc/passwd') // 'etc_passwd'
220
- * sanitizeFilename('file<name>.jpg') // 'filename.jpg'
221
- * sanitizeFilename('photo (1).jpg') // 'photo_1.jpg'
222
- * sanitizeFilename('.htaccess') // 'htaccess'
223
- */
224
- declare function sanitizeFilename(filename: string): string;
225
- /**
226
- * Validate a file upload for security.
227
- *
228
- * Checks file size, MIME type, extension, magic bytes, and dangerous patterns.
229
- * Returns a result with validation errors and a sanitized filename.
230
- *
231
- * @param file - File metadata and optional content
232
- * @param options - Validation options
233
- * @returns Validation result
234
- *
235
- * @example
236
- * const result = validateFile(
237
- * { filename: 'photo.jpg', mimetype: 'image/jpeg', size: 1024, buffer },
238
- * { allowedTypes: ['image/jpeg', 'image/png'], maxSize: 2 * 1024 * 1024 }
239
- * );
240
- * if (!result.valid) {
241
- * return res.status(400).json({ errors: result.errors });
242
- * }
243
- * // Use result.sanitizedFilename for storage
244
- *
245
- * @example
246
- * // Block executables only (no whitelist)
247
- * const result = validateFile(file, { blockExecutables: true });
248
- */
249
- declare function validateFile(file: FileInput, options?: ValidateFileOptions): ValidateFileResult;
250
- /**
251
- * Check if a file extension is considered dangerous/executable.
252
- *
253
- * @param filename - Filename or extension to check
254
- * @returns true if the extension is dangerous
255
- */
256
- declare function isDangerousExtension(filename: string): boolean;
257
-
258
- /**
259
- * @module @arcis/node/validation/email
260
- * Advanced email validation with disposable detection and typo suggestions.
261
- *
262
- * Three levels of validation:
263
- * 1. Syntax — RFC-compliant format checking
264
- * 2. Domain intelligence — disposable/free provider detection, typo correction
265
- * 3. MX verification — DNS MX record lookup (async, optional)
266
- *
267
- * @example
268
- * const result = validateEmail('user@tempmail.com');
269
- * // { valid: false, reason: 'disposable' }
270
- *
271
- * const result = validateEmail('user@gmial.com');
272
- * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }
273
- */
274
- interface EmailValidationOptions {
275
- /** Check for disposable email providers. Default: true */
276
- checkDisposable?: boolean;
277
- /** Suggest corrections for typos. Default: true */
278
- suggestTypoFix?: boolean;
279
- /** Verify MX records via DNS. Default: false */
280
- checkMx?: boolean;
281
- /** Additional blocked domains */
282
- blockedDomains?: string[];
283
- /** Additional allowed domains (bypasses disposable check) */
284
- allowedDomains?: string[];
285
- }
286
- interface EmailValidationResult {
287
- /** Whether the email is valid */
288
- valid: boolean;
289
- /** Reason for the result */
290
- reason: 'valid' | 'invalid_syntax' | 'disposable' | 'no_mx' | 'blocked' | 'typo';
291
- /** Suggested correction if a typo was detected */
292
- suggestion: string | null;
293
- /** Whether the domain is a free email provider */
294
- isFree: boolean;
295
- /** Whether the domain is a disposable email provider */
296
- isDisposable: boolean;
297
- /** The normalized email address */
298
- normalized: string;
299
- }
300
- /**
301
- * Validate an email address with syntax checking, disposable detection,
302
- * and typo suggestions.
303
- *
304
- * @param email - Email address to validate
305
- * @param options - Validation options
306
- * @returns Validation result
307
- *
308
- * @example
309
- * validateEmail('user@gmail.com')
310
- * // { valid: true, reason: 'valid', isFree: true }
311
- *
312
- * validateEmail('user@tempmail.com')
313
- * // { valid: false, reason: 'disposable' }
314
- *
315
- * validateEmail('user@gmial.com')
316
- * // { valid: true, reason: 'typo', suggestion: 'user@gmail.com' }
317
- */
318
- declare function validateEmail(email: string, options?: EmailValidationOptions): EmailValidationResult;
319
- /**
320
- * Verify that the email domain has MX records (can receive email).
321
- *
322
- * This performs a DNS lookup and requires network access.
323
- * Use for registration flows where you need high confidence.
324
- *
325
- * @param email - Email address to verify
326
- * @returns True if the domain has MX records
327
- *
328
- * @example
329
- * if (await verifyEmailMx('user@example.com')) {
330
- * // Domain can receive email
331
- * }
332
- */
333
- declare function verifyEmailMx(email: string): Promise<boolean>;
334
- /**
335
- * Quick check if an email address has valid syntax.
336
- * Faster than validateEmail() — just syntax, no domain intelligence.
337
- */
338
- declare function isValidEmailSyntax(email: string): boolean;
339
-
340
- export { type EmailValidationOptions as E, type FileInput as F, type ValidateFileOptions as V, type EmailValidationResult as a, type ValidateFileResult as b, type ValidateRedirectOptions as c, type ValidateRedirectResult as d, type ValidateUrlOptions as e, type ValidateUrlResult as f, createValidator as g, isRedirectSafe as h, isDangerousExtension as i, isUrlSafe as j, isValidEmailSyntax as k, validateEmail as l, validateFile as m, validateRedirect as n, validateUrl as o, verifyEmailMx as p, sanitizeFilename as s, validate as v };