@arcis/node 1.2.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.
- package/dist/core/{index.d.mts → constants.d.ts} +21 -70
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/errors.d.ts +53 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/index.d.ts +6 -168
- package/dist/core/index.d.ts.map +1 -0
- package/dist/{types-CsOFHoD9.d.mts → core/types.d.ts} +38 -31
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.d.ts +71 -166
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +151 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +145 -5
- package/dist/index.mjs.map +1 -1
- package/dist/logging/index.d.ts +4 -36
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/{index.d.mts → redactor.d.ts} +5 -9
- package/dist/logging/redactor.d.ts.map +1 -0
- package/dist/middleware/bot-detection.d.ts +86 -0
- package/dist/middleware/bot-detection.d.ts.map +1 -0
- package/dist/middleware/cookies.d.ts +48 -0
- package/dist/middleware/cookies.d.ts.map +1 -0
- package/dist/middleware/cors.d.ts +65 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/csrf.d.ts +109 -0
- package/dist/middleware/csrf.d.ts.map +1 -0
- package/dist/middleware/error-handler.d.ts +43 -0
- package/dist/middleware/error-handler.d.ts.map +1 -0
- package/dist/middleware/headers.d.ts +29 -0
- package/dist/middleware/headers.d.ts.map +1 -0
- package/dist/middleware/hpp.d.ts +56 -0
- package/dist/middleware/hpp.d.ts.map +1 -0
- package/dist/middleware/index.d.ts +16 -3
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +28 -3
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +28 -3
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/middleware/main.d.ts +40 -0
- package/dist/middleware/main.d.ts.map +1 -0
- package/dist/middleware/rate-limit-sliding.d.ts +46 -0
- package/dist/middleware/rate-limit-sliding.d.ts.map +1 -0
- package/dist/middleware/rate-limit-token.d.ts +51 -0
- package/dist/middleware/rate-limit-token.d.ts.map +1 -0
- package/dist/middleware/rate-limit.d.ts +34 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/sanitizers/command.d.ts +28 -0
- package/dist/sanitizers/command.d.ts.map +1 -0
- package/dist/sanitizers/encode.d.ts +46 -0
- package/dist/sanitizers/encode.d.ts.map +1 -0
- package/dist/sanitizers/headers.d.ts +46 -0
- package/dist/sanitizers/headers.d.ts.map +1 -0
- package/dist/sanitizers/index.d.ts +17 -22
- package/dist/sanitizers/index.d.ts.map +1 -0
- package/dist/sanitizers/index.js +72 -0
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +68 -1
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/sanitizers/jsonp.d.ts +34 -0
- package/dist/sanitizers/jsonp.d.ts.map +1 -0
- package/dist/sanitizers/nosql.d.ts +31 -0
- package/dist/sanitizers/nosql.d.ts.map +1 -0
- package/dist/sanitizers/path.d.ts +28 -0
- package/dist/sanitizers/path.d.ts.map +1 -0
- package/dist/sanitizers/pii.d.ts +80 -0
- package/dist/sanitizers/pii.d.ts.map +1 -0
- package/dist/sanitizers/prototype.d.ts +34 -0
- package/dist/sanitizers/prototype.d.ts.map +1 -0
- package/dist/sanitizers/sanitize.d.ts +51 -0
- package/dist/sanitizers/sanitize.d.ts.map +1 -0
- package/dist/sanitizers/sql.d.ts +28 -0
- package/dist/sanitizers/sql.d.ts.map +1 -0
- package/dist/sanitizers/ssti.d.ts +20 -0
- package/dist/sanitizers/ssti.d.ts.map +1 -0
- package/dist/sanitizers/utils.d.ts +19 -0
- package/dist/sanitizers/utils.d.ts.map +1 -0
- package/dist/sanitizers/xss.d.ts +35 -0
- package/dist/sanitizers/xss.d.ts.map +1 -0
- package/dist/sanitizers/xxe.d.ts +20 -0
- package/dist/sanitizers/xxe.d.ts.map +1 -0
- package/dist/stores/index.d.ts +6 -104
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/memory.d.ts +35 -0
- package/dist/stores/memory.d.ts.map +1 -0
- package/dist/stores/{index.d.mts → redis.d.ts} +6 -45
- package/dist/stores/redis.d.ts.map +1 -0
- package/dist/utils/duration.d.ts +34 -0
- package/dist/utils/duration.d.ts.map +1 -0
- package/dist/utils/fingerprint.d.ts +64 -0
- package/dist/utils/fingerprint.d.ts.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +188 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +182 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/ip.d.ts +70 -0
- package/dist/utils/ip.d.ts.map +1 -0
- package/dist/validation/email.d.ts +82 -0
- package/dist/validation/email.d.ts.map +1 -0
- package/dist/validation/file.d.ts +90 -0
- package/dist/validation/file.d.ts.map +1 -0
- package/dist/validation/index.d.ts +10 -3
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/redirect.d.ts +64 -0
- package/dist/validation/redirect.d.ts.map +1 -0
- package/dist/validation/schema.d.ts +36 -0
- package/dist/validation/schema.d.ts.map +1 -0
- package/dist/validation/url.d.ts +65 -0
- package/dist/validation/url.d.ts.map +1 -0
- package/package.json +8 -6
- package/dist/index-A-m-pPeW.d.mts +0 -340
- package/dist/index-CgK94hY_.d.mts +0 -532
- package/dist/index-Co5kPRZz.d.ts +0 -340
- package/dist/index-D_bdJcF0.d.ts +0 -532
- package/dist/index.d.mts +0 -175
- package/dist/middleware/index.d.mts +0 -3
- package/dist/pii-CXcHMlnX.d.mts +0 -438
- package/dist/pii-DhNpl7M3.d.ts +0 -438
- package/dist/sanitizers/index.d.mts +0 -24
- package/dist/types-CsOFHoD9.d.ts +0 -269
- 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-D_bdJcF0.js';
|
|
2
|
-
export { P as PiiMatch, F as PiiRedactOptions, G as PiiScanOptions, H 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, o as isDangerousNoSqlKey, p as isDangerousProtoKey, r as redactObjectPii, q as redactPii, s as sanitizeCommand, t as sanitizeHeaderValue, u as sanitizeHeaders, v as sanitizeJsonpCallback, w as sanitizeObject, x as sanitizePath, y as sanitizeSql, z as sanitizeSsti, A as sanitizeString, B as sanitizeXss, C as sanitizeXxe, D as scanObjectPii, E as scanPii } from './pii-DhNpl7M3.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-Co5kPRZz.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-CsOFHoD9.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
|
-
*
|
|
13
|
-
*
|
|
2
|
+
* Arcis - One-line security for Node.js apps
|
|
3
|
+
* A cross-platform security library
|
|
14
4
|
*
|
|
15
|
-
*
|
|
5
|
+
* @module @arcis/node
|
|
6
|
+
* @version 1.0.0
|
|
16
7
|
*
|
|
17
8
|
* @example
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
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
|
-
* //
|
|
167
|
-
*
|
|
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
|
|
171
|
-
*
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
export {
|
|
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
|
@@ -307,7 +307,12 @@ function createHeaders(options = {}) {
|
|
|
307
307
|
hsts = true,
|
|
308
308
|
referrerPolicy = HEADERS.REFERRER_POLICY,
|
|
309
309
|
permissionsPolicy = HEADERS.PERMISSIONS_POLICY,
|
|
310
|
-
cacheControl = true
|
|
310
|
+
cacheControl = true,
|
|
311
|
+
crossOriginOpenerPolicy = "same-origin",
|
|
312
|
+
crossOriginResourcePolicy = "same-origin",
|
|
313
|
+
crossOriginEmbedderPolicy = "require-corp",
|
|
314
|
+
originAgentCluster = true,
|
|
315
|
+
dnsPrefetchControl = true
|
|
311
316
|
} = options;
|
|
312
317
|
return (req, res, next) => {
|
|
313
318
|
if (contentSecurityPolicy) {
|
|
@@ -315,7 +320,7 @@ function createHeaders(options = {}) {
|
|
|
315
320
|
res.setHeader("Content-Security-Policy", csp);
|
|
316
321
|
}
|
|
317
322
|
if (xssFilter) {
|
|
318
|
-
res.setHeader("X-XSS-Protection", "
|
|
323
|
+
res.setHeader("X-XSS-Protection", "0");
|
|
319
324
|
}
|
|
320
325
|
if (noSniff) {
|
|
321
326
|
res.setHeader("X-Content-Type-Options", HEADERS.CONTENT_TYPE_OPTIONS);
|
|
@@ -342,6 +347,21 @@ function createHeaders(options = {}) {
|
|
|
342
347
|
if (permissionsPolicy) {
|
|
343
348
|
res.setHeader("Permissions-Policy", permissionsPolicy);
|
|
344
349
|
}
|
|
350
|
+
if (crossOriginOpenerPolicy) {
|
|
351
|
+
res.setHeader("Cross-Origin-Opener-Policy", crossOriginOpenerPolicy);
|
|
352
|
+
}
|
|
353
|
+
if (crossOriginResourcePolicy) {
|
|
354
|
+
res.setHeader("Cross-Origin-Resource-Policy", crossOriginResourcePolicy);
|
|
355
|
+
}
|
|
356
|
+
if (crossOriginEmbedderPolicy) {
|
|
357
|
+
res.setHeader("Cross-Origin-Embedder-Policy", crossOriginEmbedderPolicy);
|
|
358
|
+
}
|
|
359
|
+
if (originAgentCluster) {
|
|
360
|
+
res.setHeader("Origin-Agent-Cluster", "?1");
|
|
361
|
+
}
|
|
362
|
+
if (dnsPrefetchControl) {
|
|
363
|
+
res.setHeader("X-DNS-Prefetch-Control", "off");
|
|
364
|
+
}
|
|
345
365
|
res.setHeader("X-Permitted-Cross-Domain-Policies", "none");
|
|
346
366
|
if (cacheControl) {
|
|
347
367
|
const cacheControlValue = typeof cacheControl === "string" ? cacheControl : HEADERS.CACHE_CONTROL;
|
|
@@ -1249,6 +1269,73 @@ function redactObjectPii(obj, options = {}) {
|
|
|
1249
1269
|
return result;
|
|
1250
1270
|
}
|
|
1251
1271
|
|
|
1272
|
+
// src/sanitizers/encode.ts
|
|
1273
|
+
var HTML_ENTITIES = {
|
|
1274
|
+
"&": "&",
|
|
1275
|
+
"<": "<",
|
|
1276
|
+
">": ">",
|
|
1277
|
+
'"': """,
|
|
1278
|
+
"'": "'"
|
|
1279
|
+
};
|
|
1280
|
+
var HTML_ENCODE_RE = /[&<>"']/g;
|
|
1281
|
+
function encodeForHtml(value) {
|
|
1282
|
+
if (!value) return "";
|
|
1283
|
+
return value.replace(HTML_ENCODE_RE, (ch) => HTML_ENTITIES[ch]);
|
|
1284
|
+
}
|
|
1285
|
+
function encodeForAttribute(value) {
|
|
1286
|
+
if (!value) return "";
|
|
1287
|
+
let result = "";
|
|
1288
|
+
for (let i = 0; i < value.length; i++) {
|
|
1289
|
+
const ch = value.charCodeAt(i);
|
|
1290
|
+
if (ch >= 48 && ch <= 57 || // 0-9
|
|
1291
|
+
ch >= 65 && ch <= 90 || // A-Z
|
|
1292
|
+
ch >= 97 && ch <= 122) {
|
|
1293
|
+
result += value[i];
|
|
1294
|
+
} else {
|
|
1295
|
+
result += `&#x${ch.toString(16).toUpperCase()};`;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return result;
|
|
1299
|
+
}
|
|
1300
|
+
function encodeForJs(value) {
|
|
1301
|
+
if (!value) return "";
|
|
1302
|
+
let result = "";
|
|
1303
|
+
for (let i = 0; i < value.length; i++) {
|
|
1304
|
+
const ch = value.charCodeAt(i);
|
|
1305
|
+
if (ch >= 48 && ch <= 57 || // 0-9
|
|
1306
|
+
ch >= 65 && ch <= 90 || // A-Z
|
|
1307
|
+
ch >= 97 && ch <= 122) {
|
|
1308
|
+
result += value[i];
|
|
1309
|
+
} else if (ch < 256) {
|
|
1310
|
+
result += `\\x${ch.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
1311
|
+
} else {
|
|
1312
|
+
result += `\\u${ch.toString(16).toUpperCase().padStart(4, "0")}`;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
return result;
|
|
1316
|
+
}
|
|
1317
|
+
function encodeForUrl(value) {
|
|
1318
|
+
if (!value) return "";
|
|
1319
|
+
return encodeURIComponent(value).replace(/[!'()*]/g, (ch) => {
|
|
1320
|
+
return `%${ch.charCodeAt(0).toString(16).toUpperCase()}`;
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
function encodeForCss(value) {
|
|
1324
|
+
if (!value) return "";
|
|
1325
|
+
let result = "";
|
|
1326
|
+
for (let i = 0; i < value.length; i++) {
|
|
1327
|
+
const ch = value.charCodeAt(i);
|
|
1328
|
+
if (ch >= 48 && ch <= 57 || // 0-9
|
|
1329
|
+
ch >= 65 && ch <= 90 || // A-Z
|
|
1330
|
+
ch >= 97 && ch <= 122) {
|
|
1331
|
+
result += value[i];
|
|
1332
|
+
} else {
|
|
1333
|
+
result += `\\${ch.toString(16).toUpperCase()} `;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
return result;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1252
1339
|
// src/validation/schema.ts
|
|
1253
1340
|
function validate(schema, source = "body") {
|
|
1254
1341
|
return (req, res, next) => {
|
|
@@ -2755,12 +2842,14 @@ function getRequestToken(req, headerName, fieldName) {
|
|
|
2755
2842
|
return void 0;
|
|
2756
2843
|
}
|
|
2757
2844
|
function csrfProtection(options = {}) {
|
|
2758
|
-
const
|
|
2845
|
+
const baseCookieName = options.cookieName ?? DEFAULTS.cookieName;
|
|
2846
|
+
const cookieName = options.useHostPrefix ? `__Host-${baseCookieName}` : baseCookieName;
|
|
2759
2847
|
const headerName = options.headerName ?? DEFAULTS.headerName;
|
|
2760
2848
|
const fieldName = options.fieldName ?? DEFAULTS.fieldName;
|
|
2761
2849
|
const tokenLength = options.tokenLength ?? DEFAULTS.tokenLength;
|
|
2762
2850
|
const protectedMethods = options.protectedMethods ?? [...DEFAULTS.protectedMethods];
|
|
2763
2851
|
const excludePaths = options.excludePaths ?? [];
|
|
2852
|
+
const skipCsrf = options.skipCsrf;
|
|
2764
2853
|
const isProduction = process.env.NODE_ENV === "production";
|
|
2765
2854
|
const cookieOpts = {
|
|
2766
2855
|
path: options.cookie?.path ?? "/",
|
|
@@ -2780,6 +2869,9 @@ function csrfProtection(options = {}) {
|
|
|
2780
2869
|
const protectedSet = new Set(protectedMethods.map((m) => m.toUpperCase()));
|
|
2781
2870
|
return (req, res, next) => {
|
|
2782
2871
|
const method = req.method.toUpperCase();
|
|
2872
|
+
if (skipCsrf && skipCsrf(req)) {
|
|
2873
|
+
return next();
|
|
2874
|
+
}
|
|
2783
2875
|
const requestPath = req.path || req.url;
|
|
2784
2876
|
if (excludePaths.some((p) => requestPath === p || requestPath.startsWith(p + "/"))) {
|
|
2785
2877
|
return next();
|
|
@@ -2836,6 +2928,54 @@ function escapeRegex(str) {
|
|
|
2836
2928
|
}
|
|
2837
2929
|
var createCsrf = csrfProtection;
|
|
2838
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
|
+
|
|
2839
2979
|
// src/utils/ip.ts
|
|
2840
2980
|
var PLATFORM_HEADERS = {
|
|
2841
2981
|
cloudflare: "cf-connecting-ip",
|
|
@@ -2956,7 +3096,7 @@ function fingerprint(req, options = {}) {
|
|
|
2956
3096
|
components.push(`enc:${getHeader2(req, "accept-encoding")}`);
|
|
2957
3097
|
}
|
|
2958
3098
|
for (const c of custom) {
|
|
2959
|
-
if (c
|
|
3099
|
+
if (c !== null && c !== void 0) components.push(`custom:${c}`);
|
|
2960
3100
|
}
|
|
2961
3101
|
components.sort();
|
|
2962
3102
|
const hash = crypto.createHash("sha256");
|
|
@@ -3121,6 +3261,7 @@ exports.createCors = createCors;
|
|
|
3121
3261
|
exports.createCsrf = createCsrf;
|
|
3122
3262
|
exports.createErrorHandler = createErrorHandler;
|
|
3123
3263
|
exports.createHeaders = createHeaders;
|
|
3264
|
+
exports.createHpp = createHpp;
|
|
3124
3265
|
exports.createRateLimiter = createRateLimiter;
|
|
3125
3266
|
exports.createRedactor = createRedactor;
|
|
3126
3267
|
exports.createRedisStore = createRedisStore;
|
|
@@ -3145,11 +3286,17 @@ exports.detectSql = detectSql;
|
|
|
3145
3286
|
exports.detectSsti = detectSsti;
|
|
3146
3287
|
exports.detectXss = detectXss;
|
|
3147
3288
|
exports.detectXxe = detectXxe;
|
|
3289
|
+
exports.encodeForAttribute = encodeForAttribute;
|
|
3290
|
+
exports.encodeForCss = encodeForCss;
|
|
3291
|
+
exports.encodeForHtml = encodeForHtml;
|
|
3292
|
+
exports.encodeForJs = encodeForJs;
|
|
3293
|
+
exports.encodeForUrl = encodeForUrl;
|
|
3148
3294
|
exports.enforceSecureCookie = enforceSecureCookie;
|
|
3149
3295
|
exports.errorHandler = errorHandler;
|
|
3150
3296
|
exports.fingerprint = fingerprint;
|
|
3151
3297
|
exports.formatDuration = formatDuration;
|
|
3152
3298
|
exports.generateCsrfToken = generateCsrfToken;
|
|
3299
|
+
exports.hpp = hpp;
|
|
3153
3300
|
exports.isDangerousExtension = isDangerousExtension;
|
|
3154
3301
|
exports.isDangerousNoSqlKey = isDangerousNoSqlKey;
|
|
3155
3302
|
exports.isDangerousProtoKey = isDangerousProtoKey;
|