@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
package/dist/index.d.ts CHANGED
@@ -1,175 +1,80 @@
1
- export { B as BotCategory, a as BotDetectionResult, b as BotProtectionOptions, C as CorsOptions, c as CsrfOptions, S as SecureCookieOptions, d as SlidingWindowMiddleware, e as SlidingWindowOptions, T as TokenBucketMiddleware, f as TokenBucketOptions, g as arcis, h as arcisFunction, i as botProtection, j as createCors, k as createCsrf, l as createErrorHandler, m as createHeaders, n as createRateLimiter, o as createSecureCookies, p as createSlidingWindowLimiter, q as createTokenBucketLimiter, r as csrfProtection, h as default, s as detectBot, t as enforceSecureCookie, u as errorHandler, v as generateCsrfToken, w as rateLimit, x as safeCors, y as secureCookieDefaults, z as securityHeaders, A as validateCsrfToken } from './index-BAhgn9V2.js';
2
- export { P as PiiMatch, K as PiiRedactOptions, L as PiiScanOptions, M as PiiType, c as createSanitizer, d as detectCommandInjection, a as detectHeaderInjection, b as detectJsonpInjection, e as detectNoSqlInjection, f as detectPathTraversal, g as detectPii, h as detectPrototypePollution, i as detectSql, j as detectSsti, k as detectXss, l as detectXxe, m as encodeForAttribute, n as encodeForCss, o as encodeForHtml, p as encodeForJs, q as encodeForUrl, t as isDangerousNoSqlKey, u as isDangerousProtoKey, v as redactObjectPii, w as redactPii, x as sanitizeCommand, y as sanitizeHeaderValue, z as sanitizeHeaders, A as sanitizeJsonpCallback, B as sanitizeObject, C as sanitizePath, D as sanitizeSql, E as sanitizeSsti, F as sanitizeString, G as sanitizeXss, H as sanitizeXxe, I as scanObjectPii, J as scanPii } from './encode-jl9sOwmA.js';
3
- export { E as EmailValidationOptions, a as EmailValidationResult, F as FileInput, V as ValidateFileOptions, b as ValidateFileResult, c as ValidateRedirectOptions, d as ValidateRedirectResult, e as ValidateUrlOptions, f as ValidateUrlResult, g as createValidator, i as isDangerousExtension, h as isRedirectSafe, j as isUrlSafe, k as isValidEmailSyntax, s as sanitizeFilename, v as validate, l as validateEmail, m as validateFile, n as validateRedirect, o as validateUrl, p as verifyEmailMx } from './index-BGNKspqH.js';
4
- import { IncomingMessage } from 'http';
5
- export { createRedactor, createSafeLogger, safeLog } from './logging/index.js';
6
- export { MemoryStore, RedisClientLike, RedisStore, RedisStoreOptions, createRedisStore } from './stores/index.js';
7
- export { A as ArcisFunction, a as ArcisMiddleware, b as ArcisOptions, E as ErrorHandlerOptions, F as FieldValidator, H as HeaderOptions, c as HstsOptions, d as HttpError, L as LogOptions, R as RateLimitEntry, e as RateLimitOptions, f as RateLimitResult, g as RateLimitStore, h as RateLimiterMiddleware, S as SafeLogger, i as SanitizeOptions, j as SanitizeResult, T as ThreatInfo, k as ThreatType, V as ValidationConfig, l as ValidationError, m as ValidationResult, n as ValidationSchema } from './types-BOkx5YJc.js';
8
- export { ArcisError, ArcisValidationError, BLOCKED, ERRORS, HEADERS, INPUT, InputTooLargeError, RATE_LIMIT, REDACTION, RateLimitError, SanitizationError, SecurityThreatError, VALIDATION } from './core/index.js';
9
- import 'express';
10
-
11
1
  /**
12
- * @module @arcis/node/utils/duration
13
- * Parse human-readable duration strings into milliseconds.
2
+ * Arcis - One-line security for Node.js apps
3
+ * A cross-platform security library
14
4
  *
15
- * Supports: ms, s, m, h, d
5
+ * @module @arcis/node
6
+ * @version 1.0.0
16
7
  *
17
8
  * @example
18
- * parseDuration('5m') // 300000
19
- * parseDuration('2h') // 7200000
20
- * parseDuration(60000) // 60000 (passthrough)
21
- * parseDuration('500ms') // 500
22
- */
23
- /**
24
- * Parse a duration string or number into milliseconds.
25
- *
26
- * @param value - Duration string (e.g. "5m", "2h", "30s") or number (ms)
27
- * @returns Duration in milliseconds
28
- * @throws {Error} If the value is not a valid duration
29
- *
30
- * @example
31
- * parseDuration('15m') // 900000
32
- * parseDuration('1d') // 86400000
33
- * parseDuration('500ms') // 500
34
- * parseDuration(60000) // 60000
35
- */
36
- declare function parseDuration(value: string | number): number;
37
- /**
38
- * Format milliseconds into a human-readable duration string.
39
- *
40
- * @param ms - Duration in milliseconds
41
- * @returns Human-readable string (e.g. "5m", "2h 30m")
42
- */
43
- declare function formatDuration(ms: number): string;
44
-
45
- /**
46
- * @module @arcis/node/utils/ip
47
- * Platform-aware client IP detection.
48
- *
49
- * Prevents IP spoofing by reading platform-specific headers
50
- * instead of blindly trusting X-Forwarded-For.
51
- *
52
- * @example
53
- * // Auto-detect platform from environment
54
- * const ip = detectClientIp(req);
55
- *
56
- * // Explicit platform
57
- * const ip = detectClientIp(req, { platform: 'cloudflare' });
58
- */
59
-
60
- type Platform = 'auto' | 'cloudflare' | 'vercel' | 'flyio' | 'render' | 'firebase' | 'aws-alb' | 'generic';
61
- interface DetectIpOptions {
62
- /** Platform to use for header selection. Default: 'auto' */
63
- platform?: Platform;
64
- /** Number of trusted proxies (for X-Forwarded-For parsing). Default: 1 */
65
- trustedProxyCount?: number;
66
- }
67
- interface RequestLike$1 {
68
- headers: Record<string, string | string[] | undefined>;
69
- socket?: {
70
- remoteAddress?: string;
71
- };
72
- connection?: {
73
- remoteAddress?: string;
74
- };
75
- ip?: string;
76
- }
77
- /**
78
- * Detect the real client IP address from a request.
79
- *
80
- * Uses platform-specific headers when available to prevent IP spoofing.
81
- * Falls back to X-Forwarded-For (parsed from the right) and then
82
- * the socket remote address.
83
- *
84
- * @param req - HTTP request object (Express, raw http, etc.)
85
- * @param options - Detection options
86
- * @returns Client IP address, or 'unknown' if unresolvable
87
- *
88
- * @example
89
- * // Auto-detect platform
90
- * app.use((req, res, next) => {
91
- * const clientIp = detectClientIp(req);
92
- * console.log('Client IP:', clientIp);
93
- * next();
94
- * });
95
- *
96
- * @example
97
- * // Behind Cloudflare
98
- * const ip = detectClientIp(req, { platform: 'cloudflare' });
99
- *
100
- * @example
101
- * // Behind 2 proxies (e.g. CDN + load balancer)
102
- * const ip = detectClientIp(req, { trustedProxyCount: 2 });
103
- */
104
- declare function detectClientIp(req: RequestLike$1 | IncomingMessage, options?: DetectIpOptions): string;
105
- /**
106
- * Check if an IP address is a private/internal address.
107
- *
108
- * Detects: loopback, private ranges (RFC 1918), link-local, IPv6 equivalents.
109
- */
110
- declare function isPrivateIp(ip: string): boolean;
111
-
112
- /**
113
- * @module @arcis/node/utils/fingerprint
114
- * Deterministic request fingerprinting via SHA-256.
115
- *
116
- * Generates a stable hash from request characteristics for
117
- * rate limiting keys, abuse detection, and analytics.
118
- *
119
- * @example
120
- * const fp = await fingerprint(req);
121
- * // "a3f2b8c1d4e5..."
122
- */
123
-
124
- interface FingerprintOptions {
125
- /** Include IP address in fingerprint. Default: true */
126
- ip?: boolean;
127
- /** Include User-Agent header. Default: true */
128
- userAgent?: boolean;
129
- /** Include Accept header. Default: true */
130
- accept?: boolean;
131
- /** Include Accept-Language header. Default: true */
132
- acceptLanguage?: boolean;
133
- /** Include Accept-Encoding header. Default: true */
134
- acceptEncoding?: boolean;
135
- /** Additional custom components to include */
136
- custom?: string[];
137
- /** IP detection options */
138
- ipOptions?: DetectIpOptions;
139
- }
140
- interface RequestLike {
141
- headers: Record<string, string | string[] | undefined>;
142
- socket?: {
143
- remoteAddress?: string;
144
- };
145
- connection?: {
146
- remoteAddress?: string;
147
- };
148
- ip?: string;
149
- }
150
- /**
151
- * Generate a deterministic fingerprint for a request.
152
- *
153
- * Creates a SHA-256 hash from configurable request components.
154
- * The fingerprint is stable across requests from the same client
155
- * (same IP, browser, language settings).
156
- *
157
- * @param req - HTTP request object
158
- * @param options - Fingerprint configuration
159
- * @returns Hex-encoded SHA-256 hash (64 characters)
160
- *
161
- * @example
162
- * // Default fingerprint (IP + UA + Accept headers)
163
- * const fp = fingerprint(req);
9
+ * // Full protection (recommended)
10
+ * import { arcis } from '@arcis/node';
11
+ * app.use(arcis());
164
12
  *
165
13
  * @example
166
- * // IP-only fingerprint (for simple rate limiting)
167
- * const fp = fingerprint(req, { userAgent: false, accept: false, acceptLanguage: false, acceptEncoding: false });
14
+ * // Granular control
15
+ * app.use(arcis.headers());
16
+ * app.use(arcis.rateLimit({ max: 100, windowMs: 60000 }));
17
+ * app.use(arcis.sanitize());
168
18
  *
169
19
  * @example
170
- * // With custom components
171
- * const fp = fingerprint(req, { custom: [req.body?.userId] });
20
+ * // With validation
21
+ * app.post('/users', arcis.validate({
22
+ * email: { type: 'email', required: true },
23
+ * age: { type: 'number', min: 0, max: 150 }
24
+ * }), handler);
172
25
  */
173
- declare function fingerprint(req: RequestLike, options?: FingerprintOptions): string;
174
-
175
- export { type DetectIpOptions, type FingerprintOptions, type Platform, detectClientIp, fingerprint, formatDuration, isPrivateIp, parseDuration };
26
+ export { arcis, arcisFunction } from './middleware/main';
27
+ export { default } from './middleware/main';
28
+ export { createRateLimiter, rateLimit } from './middleware/rate-limit';
29
+ export { createSlidingWindowLimiter } from './middleware/rate-limit-sliding';
30
+ export { createTokenBucketLimiter } from './middleware/rate-limit-token';
31
+ export { createHeaders, securityHeaders } from './middleware/headers';
32
+ export { errorHandler, createErrorHandler } from './middleware/error-handler';
33
+ export { safeCors, createCors } from './middleware/cors';
34
+ export { secureCookieDefaults, createSecureCookies, enforceSecureCookie } from './middleware/cookies';
35
+ export { botProtection, detectBot } from './middleware/bot-detection';
36
+ export { csrfProtection, createCsrf, generateCsrfToken, validateCsrfToken } from './middleware/csrf';
37
+ export { hpp, createHpp } from './middleware/hpp';
38
+ export { sanitizeString, sanitizeObject, createSanitizer, } from './sanitizers/sanitize';
39
+ export { sanitizeXss, detectXss } from './sanitizers/xss';
40
+ export { sanitizeSql, detectSql } from './sanitizers/sql';
41
+ export { sanitizePath, detectPathTraversal } from './sanitizers/path';
42
+ export { sanitizeCommand, detectCommandInjection } from './sanitizers/command';
43
+ export { sanitizeSsti, detectSsti } from './sanitizers/ssti';
44
+ export { sanitizeXxe, detectXxe } from './sanitizers/xxe';
45
+ export { sanitizeJsonpCallback, detectJsonpInjection } from './sanitizers/jsonp';
46
+ export { isDangerousNoSqlKey, detectNoSqlInjection } from './sanitizers/nosql';
47
+ export { isDangerousProtoKey, detectPrototypePollution } from './sanitizers/prototype';
48
+ export { sanitizeHeaderValue, sanitizeHeaders, detectHeaderInjection } from './sanitizers/headers';
49
+ export { scanPii, detectPii, redactPii, scanObjectPii, redactObjectPii } from './sanitizers/pii';
50
+ export { encodeForHtml, encodeForAttribute, encodeForJs, encodeForUrl, encodeForCss } from './sanitizers/encode';
51
+ export { validate, createValidator } from './validation/schema';
52
+ export { validateUrl, isUrlSafe } from './validation/url';
53
+ export { validateRedirect, isRedirectSafe } from './validation/redirect';
54
+ export { validateFile, sanitizeFilename, isDangerousExtension } from './validation/file';
55
+ export { validateEmail, verifyEmailMx, isValidEmailSyntax } from './validation/email';
56
+ export { parseDuration, formatDuration } from './utils/duration';
57
+ export { detectClientIp, isPrivateIp } from './utils/ip';
58
+ export { fingerprint } from './utils/fingerprint';
59
+ export { createSafeLogger, createRedactor, safeLog } from './logging/redactor';
60
+ export { MemoryStore } from './stores/memory';
61
+ export { RedisStore, createRedisStore } from './stores/redis';
62
+ export type { ArcisOptions, ArcisFunction, ArcisMiddleware, SanitizeOptions, SanitizeResult, ThreatInfo, ThreatType, RateLimitOptions, RateLimitStore, RateLimitEntry, RateLimitResult, RateLimiterMiddleware, HeaderOptions, HstsOptions, ValidationConfig, ValidationSchema, FieldValidator, ValidationResult, ValidationError, LogOptions, SafeLogger, ErrorHandlerOptions, HttpError, } from './core/types';
63
+ export type { ValidateUrlOptions, ValidateUrlResult } from './validation/url';
64
+ export type { CorsOptions } from './middleware/cors';
65
+ export type { SecureCookieOptions } from './middleware/cookies';
66
+ export type { ValidateFileOptions, FileInput, ValidateFileResult } from './validation/file';
67
+ export type { ValidateRedirectOptions, ValidateRedirectResult } from './validation/redirect';
68
+ export type { RedisClientLike, RedisStoreOptions } from './stores/redis';
69
+ export type { Platform, DetectIpOptions } from './utils/ip';
70
+ export type { FingerprintOptions } from './utils/fingerprint';
71
+ export type { EmailValidationOptions, EmailValidationResult } from './validation/email';
72
+ export type { SlidingWindowOptions, SlidingWindowMiddleware } from './middleware/rate-limit-sliding';
73
+ export type { TokenBucketOptions, TokenBucketMiddleware } from './middleware/rate-limit-token';
74
+ export type { BotCategory, BotDetectionResult, BotProtectionOptions } from './middleware/bot-detection';
75
+ export type { CsrfOptions } from './middleware/csrf';
76
+ export type { HppOptions } from './middleware/hpp';
77
+ export type { PiiType, PiiMatch, PiiScanOptions, PiiRedactOptions } from './sanitizers/pii';
78
+ export { ArcisError, ArcisValidationError, RateLimitError, InputTooLargeError, SecurityThreatError, SanitizationError, } from './core/errors';
79
+ export { INPUT, RATE_LIMIT, HEADERS, REDACTION, VALIDATION, ERRORS, BLOCKED, } from './core/constants';
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2842,12 +2842,14 @@ function getRequestToken(req, headerName, fieldName) {
2842
2842
  return void 0;
2843
2843
  }
2844
2844
  function csrfProtection(options = {}) {
2845
- const cookieName = options.cookieName ?? DEFAULTS.cookieName;
2845
+ const baseCookieName = options.cookieName ?? DEFAULTS.cookieName;
2846
+ const cookieName = options.useHostPrefix ? `__Host-${baseCookieName}` : baseCookieName;
2846
2847
  const headerName = options.headerName ?? DEFAULTS.headerName;
2847
2848
  const fieldName = options.fieldName ?? DEFAULTS.fieldName;
2848
2849
  const tokenLength = options.tokenLength ?? DEFAULTS.tokenLength;
2849
2850
  const protectedMethods = options.protectedMethods ?? [...DEFAULTS.protectedMethods];
2850
2851
  const excludePaths = options.excludePaths ?? [];
2852
+ const skipCsrf = options.skipCsrf;
2851
2853
  const isProduction = process.env.NODE_ENV === "production";
2852
2854
  const cookieOpts = {
2853
2855
  path: options.cookie?.path ?? "/",
@@ -2867,6 +2869,9 @@ function csrfProtection(options = {}) {
2867
2869
  const protectedSet = new Set(protectedMethods.map((m) => m.toUpperCase()));
2868
2870
  return (req, res, next) => {
2869
2871
  const method = req.method.toUpperCase();
2872
+ if (skipCsrf && skipCsrf(req)) {
2873
+ return next();
2874
+ }
2870
2875
  const requestPath = req.path || req.url;
2871
2876
  if (excludePaths.some((p) => requestPath === p || requestPath.startsWith(p + "/"))) {
2872
2877
  return next();
@@ -2923,6 +2928,54 @@ function escapeRegex(str) {
2923
2928
  }
2924
2929
  var createCsrf = csrfProtection;
2925
2930
 
2931
+ // src/middleware/hpp.ts
2932
+ function hpp(options = {}) {
2933
+ const whitelist = new Set(options.whitelist ?? []);
2934
+ const checkQuery = options.checkQuery ?? true;
2935
+ const checkBody = options.checkBody ?? true;
2936
+ return (req, _res, next) => {
2937
+ if (checkQuery && req.query && typeof req.query === "object") {
2938
+ const polluted = {};
2939
+ const clean = {};
2940
+ for (const [key, value] of Object.entries(req.query)) {
2941
+ if (Array.isArray(value)) {
2942
+ const strings = value.filter((v) => typeof v === "string");
2943
+ if (whitelist.has(key)) {
2944
+ clean[key] = strings;
2945
+ } else {
2946
+ polluted[key] = strings;
2947
+ clean[key] = strings[strings.length - 1] ?? "";
2948
+ }
2949
+ } else {
2950
+ clean[key] = value;
2951
+ }
2952
+ }
2953
+ req.queryPolluted = polluted;
2954
+ Object.defineProperty(req, "query", { value: clean, writable: true, configurable: true });
2955
+ }
2956
+ if (checkBody && req.body && typeof req.body === "object" && !Array.isArray(req.body)) {
2957
+ const polluted = {};
2958
+ const clean = {};
2959
+ for (const [key, value] of Object.entries(req.body)) {
2960
+ if (Array.isArray(value)) {
2961
+ if (whitelist.has(key)) {
2962
+ clean[key] = value;
2963
+ } else {
2964
+ polluted[key] = value;
2965
+ clean[key] = value[value.length - 1];
2966
+ }
2967
+ } else {
2968
+ clean[key] = value;
2969
+ }
2970
+ }
2971
+ req.bodyPolluted = polluted;
2972
+ Object.defineProperty(req, "body", { value: clean, writable: true, configurable: true });
2973
+ }
2974
+ next();
2975
+ };
2976
+ }
2977
+ var createHpp = hpp;
2978
+
2926
2979
  // src/utils/ip.ts
2927
2980
  var PLATFORM_HEADERS = {
2928
2981
  cloudflare: "cf-connecting-ip",
@@ -3043,7 +3096,7 @@ function fingerprint(req, options = {}) {
3043
3096
  components.push(`enc:${getHeader2(req, "accept-encoding")}`);
3044
3097
  }
3045
3098
  for (const c of custom) {
3046
- if (c != null) components.push(`custom:${c}`);
3099
+ if (c !== null && c !== void 0) components.push(`custom:${c}`);
3047
3100
  }
3048
3101
  components.sort();
3049
3102
  const hash = crypto.createHash("sha256");
@@ -3208,6 +3261,7 @@ exports.createCors = createCors;
3208
3261
  exports.createCsrf = createCsrf;
3209
3262
  exports.createErrorHandler = createErrorHandler;
3210
3263
  exports.createHeaders = createHeaders;
3264
+ exports.createHpp = createHpp;
3211
3265
  exports.createRateLimiter = createRateLimiter;
3212
3266
  exports.createRedactor = createRedactor;
3213
3267
  exports.createRedisStore = createRedisStore;
@@ -3242,6 +3296,7 @@ exports.errorHandler = errorHandler;
3242
3296
  exports.fingerprint = fingerprint;
3243
3297
  exports.formatDuration = formatDuration;
3244
3298
  exports.generateCsrfToken = generateCsrfToken;
3299
+ exports.hpp = hpp;
3245
3300
  exports.isDangerousExtension = isDangerousExtension;
3246
3301
  exports.isDangerousNoSqlKey = isDangerousNoSqlKey;
3247
3302
  exports.isDangerousProtoKey = isDangerousProtoKey;