@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.
- 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-BOkx5YJc.d.mts → core/types.d.ts} +27 -30
- 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 +57 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +56 -3
- 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 +6 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +6 -1
- 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/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/encode-CrQCGlBq.d.mts +0 -484
- package/dist/encode-jl9sOwmA.d.ts +0 -484
- package/dist/index-BAhgn9V2.d.ts +0 -532
- package/dist/index-BGNKspqH.d.ts +0 -340
- package/dist/index-Cd02z-0j.d.mts +0 -340
- package/dist/index-DgJtWMSj.d.mts +0 -532
- package/dist/index.d.mts +0 -175
- package/dist/middleware/index.d.mts +0 -3
- package/dist/sanitizers/index.d.mts +0 -24
- package/dist/types-BOkx5YJc.d.ts +0 -279
- package/dist/validation/index.d.mts +0 -3
package/dist/logging/index.d.ts
CHANGED
|
@@ -1,38 +1,6 @@
|
|
|
1
|
-
import { L as LogOptions, S as SafeLogger } from '../types-BOkx5YJc.js';
|
|
2
|
-
import 'express';
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
|
-
* @module @arcis/node/logging
|
|
6
|
-
* Safe logging
|
|
2
|
+
* @module @arcis/node/logging
|
|
3
|
+
* Safe logging for Arcis
|
|
7
4
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* Create a safe logger that redacts sensitive data and prevents log injection.
|
|
11
|
-
*
|
|
12
|
-
* @param options - Logger configuration
|
|
13
|
-
* @returns SafeLogger instance
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* const logger = createSafeLogger();
|
|
17
|
-
* logger.info('User login', { email: 'user@test.com', password: 'secret' });
|
|
18
|
-
* // Logs: { "email": "user@test.com", "password": "[REDACTED]" }
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* // With custom redact keys
|
|
22
|
-
* const logger = createSafeLogger({ redactKeys: ['customToken', 'internalId'] });
|
|
23
|
-
*/
|
|
24
|
-
declare function createSafeLogger(options?: LogOptions): SafeLogger;
|
|
25
|
-
/**
|
|
26
|
-
* Create a redactor function for custom use.
|
|
27
|
-
*
|
|
28
|
-
* @param sensitiveKeys - Keys to redact
|
|
29
|
-
* @returns Redactor function
|
|
30
|
-
*/
|
|
31
|
-
declare function createRedactor(sensitiveKeys?: string[]): (obj: unknown) => unknown;
|
|
32
|
-
/**
|
|
33
|
-
* Alias for createSafeLogger
|
|
34
|
-
* @see createSafeLogger
|
|
35
|
-
*/
|
|
36
|
-
declare const safeLog: typeof createSafeLogger;
|
|
37
|
-
|
|
38
|
-
export { createRedactor, createSafeLogger, safeLog };
|
|
5
|
+
export { createSafeLogger, createRedactor, safeLog } from './redactor';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logging/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { L as LogOptions, S as SafeLogger } from '../types-BOkx5YJc.mjs';
|
|
2
|
-
import 'express';
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* @module @arcis/node/logging/redactor
|
|
6
3
|
* Safe logging with PII/secret redaction
|
|
7
4
|
*/
|
|
8
|
-
|
|
5
|
+
import type { LogOptions, SafeLogger } from '../core/types';
|
|
9
6
|
/**
|
|
10
7
|
* Create a safe logger that redacts sensitive data and prevents log injection.
|
|
11
8
|
*
|
|
@@ -21,18 +18,17 @@ import 'express';
|
|
|
21
18
|
* // With custom redact keys
|
|
22
19
|
* const logger = createSafeLogger({ redactKeys: ['customToken', 'internalId'] });
|
|
23
20
|
*/
|
|
24
|
-
declare function createSafeLogger(options?: LogOptions): SafeLogger;
|
|
21
|
+
export declare function createSafeLogger(options?: LogOptions): SafeLogger;
|
|
25
22
|
/**
|
|
26
23
|
* Create a redactor function for custom use.
|
|
27
24
|
*
|
|
28
25
|
* @param sensitiveKeys - Keys to redact
|
|
29
26
|
* @returns Redactor function
|
|
30
27
|
*/
|
|
31
|
-
declare function createRedactor(sensitiveKeys?: string[]): (obj: unknown) => unknown;
|
|
28
|
+
export declare function createRedactor(sensitiveKeys?: string[]): (obj: unknown) => unknown;
|
|
32
29
|
/**
|
|
33
30
|
* Alias for createSafeLogger
|
|
34
31
|
* @see createSafeLogger
|
|
35
32
|
*/
|
|
36
|
-
declare const safeLog: typeof createSafeLogger;
|
|
37
|
-
|
|
38
|
-
export { createRedactor, createSafeLogger, safeLog };
|
|
33
|
+
export declare const safeLog: typeof createSafeLogger;
|
|
34
|
+
//# sourceMappingURL=redactor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redactor.d.ts","sourceRoot":"","sources":["../../src/logging/redactor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAU5D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,UAAe,GAAG,UAAU,CAwErE;AA2BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,aAAa,GAAE,MAAM,EAAO,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CA2BtF;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,yBAAmB,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/bot-detection
|
|
3
|
+
* Local-only bot detection using User-Agent and behavioral signals.
|
|
4
|
+
*
|
|
5
|
+
* Categorizes requests into bot types and allows/denies based on config.
|
|
6
|
+
* No cloud calls — everything runs locally.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Block automated tools, allow search engines
|
|
10
|
+
* app.use(botProtection({
|
|
11
|
+
* allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],
|
|
12
|
+
* deny: ['AUTOMATED', 'SCRAPER'],
|
|
13
|
+
* }));
|
|
14
|
+
*/
|
|
15
|
+
import type { Request, Response, RequestHandler } from 'express';
|
|
16
|
+
export type BotCategory = 'SEARCH_ENGINE' | 'SOCIAL' | 'MONITORING' | 'AI_CRAWLER' | 'SCRAPER' | 'AUTOMATED' | 'UNKNOWN' | 'HUMAN';
|
|
17
|
+
export interface BotDetectionResult {
|
|
18
|
+
/** Whether the request appears to be from a bot */
|
|
19
|
+
isBot: boolean;
|
|
20
|
+
/** Bot category */
|
|
21
|
+
category: BotCategory;
|
|
22
|
+
/** Matched bot name (e.g. 'Googlebot', 'curl') or null */
|
|
23
|
+
name: string | null;
|
|
24
|
+
/** Confidence score: 0-1 */
|
|
25
|
+
confidence: number;
|
|
26
|
+
/** Behavioral signals detected */
|
|
27
|
+
signals: string[];
|
|
28
|
+
}
|
|
29
|
+
export interface BotProtectionOptions {
|
|
30
|
+
/** Categories to explicitly allow. Default: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'] */
|
|
31
|
+
allow?: BotCategory[];
|
|
32
|
+
/** Categories to explicitly deny. Default: ['AUTOMATED'] */
|
|
33
|
+
deny?: BotCategory[];
|
|
34
|
+
/** Action for categories not in allow or deny. Default: 'allow' */
|
|
35
|
+
defaultAction?: 'allow' | 'deny';
|
|
36
|
+
/** HTTP status code for denied bots. Default: 403 */
|
|
37
|
+
statusCode?: number;
|
|
38
|
+
/** Error message for denied bots */
|
|
39
|
+
message?: string;
|
|
40
|
+
/** Enable behavioral signal detection. Default: true */
|
|
41
|
+
detectBehavior?: boolean;
|
|
42
|
+
/** Custom handler called on detection (instead of default deny response) */
|
|
43
|
+
onDetected?: (req: Request, res: Response, result: BotDetectionResult) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Detect what kind of bot (if any) is making the request.
|
|
47
|
+
*
|
|
48
|
+
* @param req - HTTP request object
|
|
49
|
+
* @returns Detection result with category, name, confidence, and signals
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const result = detectBot(req);
|
|
53
|
+
* if (result.isBot && result.category === 'AUTOMATED') {
|
|
54
|
+
* // Block automated tools
|
|
55
|
+
* }
|
|
56
|
+
*/
|
|
57
|
+
export declare function detectBot(req: Request): BotDetectionResult;
|
|
58
|
+
/**
|
|
59
|
+
* Create Express middleware for bot protection.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Block automated tools and scrapers
|
|
63
|
+
* app.use(botProtection({
|
|
64
|
+
* allow: ['SEARCH_ENGINE', 'SOCIAL', 'MONITORING'],
|
|
65
|
+
* deny: ['AUTOMATED', 'SCRAPER'],
|
|
66
|
+
* }));
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Block everything except search engines
|
|
70
|
+
* app.use(botProtection({
|
|
71
|
+
* allow: ['SEARCH_ENGINE'],
|
|
72
|
+
* defaultAction: 'deny',
|
|
73
|
+
* }));
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Custom handler
|
|
77
|
+
* app.use(botProtection({
|
|
78
|
+
* deny: ['AUTOMATED'],
|
|
79
|
+
* onDetected: (req, res, result) => {
|
|
80
|
+
* console.log(`Bot blocked: ${result.name} (${result.category})`);
|
|
81
|
+
* res.status(403).json({ error: 'Bots not allowed' });
|
|
82
|
+
* },
|
|
83
|
+
* }));
|
|
84
|
+
*/
|
|
85
|
+
export declare function botProtection(options?: BotProtectionOptions): RequestHandler;
|
|
86
|
+
//# sourceMappingURL=bot-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-detection.d.ts","sourceRoot":"","sources":["../../src/middleware/bot-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAgB,cAAc,EAAE,MAAM,SAAS,CAAC;AAM/E,MAAM,MAAM,WAAW,GACnB,eAAe,GACf,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,WAAW,GACX,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,mBAAmB;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,0DAA0D;IAC1D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,yFAAyF;IACzF,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,mEAAmE;IACnE,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAChF;AA4JD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAmD1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,cAAc,CAgDhF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/cookies
|
|
3
|
+
* Secure cookie defaults middleware
|
|
4
|
+
*/
|
|
5
|
+
import type { RequestHandler } from 'express';
|
|
6
|
+
/** Cookie security configuration */
|
|
7
|
+
export interface SecureCookieOptions {
|
|
8
|
+
/** Force HttpOnly on all cookies. Default: true */
|
|
9
|
+
httpOnly?: boolean;
|
|
10
|
+
/** Force Secure flag (HTTPS only). Default: true in production, false in dev */
|
|
11
|
+
secure?: boolean;
|
|
12
|
+
/** SameSite attribute. Default: 'Lax' */
|
|
13
|
+
sameSite?: 'Strict' | 'Lax' | 'None' | false;
|
|
14
|
+
/** Override Path attribute. Default: undefined (keep original) */
|
|
15
|
+
path?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Enforce secure defaults on a Set-Cookie header value.
|
|
19
|
+
*/
|
|
20
|
+
export declare function enforceSecureCookie(cookieStr: string, options: Required<Omit<SecureCookieOptions, 'path'>> & {
|
|
21
|
+
path?: string;
|
|
22
|
+
}): string;
|
|
23
|
+
/**
|
|
24
|
+
* Create middleware that enforces secure cookie defaults.
|
|
25
|
+
*
|
|
26
|
+
* Intercepts Set-Cookie headers and adds missing security attributes:
|
|
27
|
+
* - HttpOnly: prevents JavaScript access (XSS cookie theft)
|
|
28
|
+
* - Secure: cookies only sent over HTTPS
|
|
29
|
+
* - SameSite: CSRF protection
|
|
30
|
+
*
|
|
31
|
+
* @param options - Cookie security configuration
|
|
32
|
+
* @returns Express middleware
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Enforce defaults on all cookies
|
|
36
|
+
* app.use(secureCookieDefaults());
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Strict SameSite for sensitive apps
|
|
40
|
+
* app.use(secureCookieDefaults({ sameSite: 'Strict' }));
|
|
41
|
+
*/
|
|
42
|
+
export declare function secureCookieDefaults(options?: SecureCookieOptions): RequestHandler;
|
|
43
|
+
/**
|
|
44
|
+
* Alias for secureCookieDefaults
|
|
45
|
+
* @see secureCookieDefaults
|
|
46
|
+
*/
|
|
47
|
+
export declare const createSecureCookies: typeof secureCookieDefaults;
|
|
48
|
+
//# sourceMappingURL=cookies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/middleware/cookies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC7C,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAUD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,MAAM,CA4CR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,mBAAwB,GAAG,cAAc,CA0BtF;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,6BAAuB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/cors
|
|
3
|
+
* Safe CORS middleware with secure defaults
|
|
4
|
+
*/
|
|
5
|
+
import type { RequestHandler } from 'express';
|
|
6
|
+
/** CORS configuration options */
|
|
7
|
+
export interface CorsOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Allowed origins. Can be:
|
|
10
|
+
* - A string: exact match (e.g., 'https://example.com')
|
|
11
|
+
* - An array: whitelist of allowed origins
|
|
12
|
+
* - A RegExp: pattern match (use with care)
|
|
13
|
+
* - A function: custom validation `(origin) => boolean`
|
|
14
|
+
* - `true`: reflect the request origin (DANGEROUS — only for dev)
|
|
15
|
+
*
|
|
16
|
+
* Default: none (no origin allowed). You must explicitly set this.
|
|
17
|
+
*/
|
|
18
|
+
origin: string | string[] | RegExp | ((origin: string) => boolean) | true;
|
|
19
|
+
/** Allowed HTTP methods. Default: ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'] */
|
|
20
|
+
methods?: string[];
|
|
21
|
+
/** Allowed headers. Default: ['Content-Type', 'Authorization'] */
|
|
22
|
+
allowedHeaders?: string[];
|
|
23
|
+
/** Headers exposed to the browser. Default: [] */
|
|
24
|
+
exposedHeaders?: string[];
|
|
25
|
+
/** Allow credentials (cookies, authorization headers). Default: false */
|
|
26
|
+
credentials?: boolean;
|
|
27
|
+
/** Preflight cache duration in seconds. Default: 600 (10 minutes) */
|
|
28
|
+
maxAge?: number;
|
|
29
|
+
/** Respond to preflight with 204 (no content). Default: true */
|
|
30
|
+
preflightContinue?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create safe CORS middleware.
|
|
34
|
+
*
|
|
35
|
+
* Unlike permissive CORS libraries, this enforces secure defaults:
|
|
36
|
+
* - No wildcard `*` when credentials are enabled
|
|
37
|
+
* - `null` origin is always blocked
|
|
38
|
+
* - `Vary: Origin` is always set for proper caching
|
|
39
|
+
* - You must explicitly configure allowed origins
|
|
40
|
+
*
|
|
41
|
+
* @param options - CORS configuration
|
|
42
|
+
* @returns Express middleware
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Allow a single origin
|
|
46
|
+
* app.use(safeCors({ origin: 'https://myapp.com' }));
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Allow multiple origins with credentials
|
|
50
|
+
* app.use(safeCors({
|
|
51
|
+
* origin: ['https://myapp.com', 'https://admin.myapp.com'],
|
|
52
|
+
* credentials: true,
|
|
53
|
+
* }));
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Development: allow all (NOT for production)
|
|
57
|
+
* app.use(safeCors({ origin: true }));
|
|
58
|
+
*/
|
|
59
|
+
export declare function safeCors(options: CorsOptions): RequestHandler;
|
|
60
|
+
/**
|
|
61
|
+
* Alias for safeCors
|
|
62
|
+
* @see safeCors
|
|
63
|
+
*/
|
|
64
|
+
export declare const createCors: typeof safeCors;
|
|
65
|
+
//# sourceMappingURL=cors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;IAE1E,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,cAAc,CAsD7D;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,iBAAW,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/csrf
|
|
3
|
+
* CSRF (Cross-Site Request Forgery) protection middleware
|
|
4
|
+
*
|
|
5
|
+
* Implements the double-submit cookie pattern:
|
|
6
|
+
* 1. Server sets a CSRF token in a cookie
|
|
7
|
+
* 2. Client must send the same token in a header or form field
|
|
8
|
+
* 3. Middleware rejects requests where cookie token !== header/field token
|
|
9
|
+
*
|
|
10
|
+
* This works because an attacker's cross-origin form submission will include
|
|
11
|
+
* the cookie automatically, but cannot read it (same-origin policy) to set
|
|
12
|
+
* the matching header.
|
|
13
|
+
*/
|
|
14
|
+
import type { Request, Response, NextFunction, RequestHandler } from 'express';
|
|
15
|
+
/** CSRF protection configuration */
|
|
16
|
+
export interface CsrfOptions {
|
|
17
|
+
/** Cookie name for the CSRF token. Default: '_csrf' */
|
|
18
|
+
cookieName?: string;
|
|
19
|
+
/** Header name to check for the token. Default: 'x-csrf-token' */
|
|
20
|
+
headerName?: string;
|
|
21
|
+
/** Form field name to check for the token. Default: '_csrf' */
|
|
22
|
+
fieldName?: string;
|
|
23
|
+
/** Token byte length (hex-encoded = 2x chars). Default: 32 */
|
|
24
|
+
tokenLength?: number;
|
|
25
|
+
/** HTTP methods to protect. Default: ['POST', 'PUT', 'PATCH', 'DELETE'] */
|
|
26
|
+
protectedMethods?: string[];
|
|
27
|
+
/** Paths to exclude from CSRF checks (e.g., webhook endpoints) */
|
|
28
|
+
excludePaths?: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Per-request skip function. If it returns true, CSRF check is skipped
|
|
31
|
+
* for that request. Useful for API key auth or signed webhooks.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* skipCsrf: (req) => Boolean(req.headers['x-api-key'])
|
|
35
|
+
*/
|
|
36
|
+
skipCsrf?: (req: Request) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Use the __Host- cookie prefix for stronger cookie security.
|
|
39
|
+
* When enabled, the browser enforces: Secure=true, no Domain, Path=/.
|
|
40
|
+
* This prevents CSRF cookie theft across subdomains.
|
|
41
|
+
* Default: false
|
|
42
|
+
*/
|
|
43
|
+
useHostPrefix?: boolean;
|
|
44
|
+
/** Cookie options */
|
|
45
|
+
cookie?: {
|
|
46
|
+
/** Cookie path. Default: '/' */
|
|
47
|
+
path?: string;
|
|
48
|
+
/** HttpOnly — set false so client JS can read it for headers. Default: false */
|
|
49
|
+
httpOnly?: boolean;
|
|
50
|
+
/** Secure flag (HTTPS only). Default: true in production */
|
|
51
|
+
secure?: boolean;
|
|
52
|
+
/** SameSite attribute. Default: 'Lax' */
|
|
53
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
54
|
+
/** Cookie domain */
|
|
55
|
+
domain?: string;
|
|
56
|
+
};
|
|
57
|
+
/** Custom error handler when CSRF validation fails */
|
|
58
|
+
onError?: (req: Request, res: Response, next: NextFunction) => void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate a cryptographically random CSRF token.
|
|
62
|
+
*
|
|
63
|
+
* @param length - Byte length (output is hex, so 2x chars). Default: 32
|
|
64
|
+
* @returns Hex-encoded random token
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const token = generateCsrfToken(); // 64 hex chars
|
|
68
|
+
*/
|
|
69
|
+
export declare function generateCsrfToken(length?: number): string;
|
|
70
|
+
/**
|
|
71
|
+
* Validate that two CSRF tokens match using constant-time comparison.
|
|
72
|
+
*
|
|
73
|
+
* @param cookieToken - Token from the cookie
|
|
74
|
+
* @param requestToken - Token from the header or form field
|
|
75
|
+
* @returns true if tokens match
|
|
76
|
+
*/
|
|
77
|
+
export declare function validateCsrfToken(cookieToken: string, requestToken: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Create CSRF protection middleware using double-submit cookie pattern.
|
|
80
|
+
*
|
|
81
|
+
* For safe methods (GET, HEAD, OPTIONS), sets a CSRF token cookie if not present.
|
|
82
|
+
* For unsafe methods (POST, PUT, PATCH, DELETE), validates the token.
|
|
83
|
+
*
|
|
84
|
+
* @param options - CSRF configuration
|
|
85
|
+
* @returns Express middleware
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Basic usage
|
|
89
|
+
* app.use(csrfProtection());
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Exclude webhook paths
|
|
93
|
+
* app.use(csrfProtection({
|
|
94
|
+
* excludePaths: ['/api/webhooks/stripe', '/api/webhooks/github']
|
|
95
|
+
* }));
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Client-side: read cookie + set header
|
|
99
|
+
* const token = document.cookie.match(/_csrf=([^;]+)/)?.[1];
|
|
100
|
+
* fetch('/api/data', {
|
|
101
|
+
* method: 'POST',
|
|
102
|
+
* headers: { 'X-CSRF-Token': token },
|
|
103
|
+
* credentials: 'same-origin'
|
|
104
|
+
* });
|
|
105
|
+
*/
|
|
106
|
+
export declare function csrfProtection(options?: CsrfOptions): RequestHandler;
|
|
107
|
+
/** Alias for csrfProtection */
|
|
108
|
+
export declare const createCsrf: typeof csrfProtection;
|
|
109
|
+
//# sourceMappingURL=csrf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csrf.d.ts","sourceRoot":"","sources":["../../src/middleware/csrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACrC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB;IACrB,MAAM,CAAC,EAAE;QACP,gCAAgC;QAChC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gFAAgF;QAChF,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,4DAA4D;QAC5D,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,yCAAyC;QACzC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;QACrC,oBAAoB;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,sDAAsD;IACtD,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;CACrE;AAUD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAUpF;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,WAAgB,GAAG,cAAc,CAmFxE;AA6CD,+BAA+B;AAC/B,eAAO,MAAM,UAAU,uBAAiB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/error-handler
|
|
3
|
+
* Production-safe error handler middleware
|
|
4
|
+
*/
|
|
5
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
6
|
+
import type { ErrorHandlerOptions } from '../core/types';
|
|
7
|
+
/**
|
|
8
|
+
* Check if an error message contains sensitive infrastructure details.
|
|
9
|
+
*/
|
|
10
|
+
export declare function containsSensitiveInfo(message: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Create Express error handler that hides sensitive details in production.
|
|
13
|
+
*
|
|
14
|
+
* Prevents information leakage by:
|
|
15
|
+
* - Hiding stack traces in production
|
|
16
|
+
* - Hiding error messages unless explicitly exposed
|
|
17
|
+
* - Scrubbing database errors, connection strings, and internal IPs
|
|
18
|
+
*
|
|
19
|
+
* @param options - Error handler configuration (or boolean for isDev)
|
|
20
|
+
* @returns Express error handling middleware
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Production mode (default) - hides error details
|
|
24
|
+
* app.use(errorHandler());
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Development mode - shows error details and stack traces
|
|
28
|
+
* app.use(errorHandler({ isDev: true }));
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // With custom logger
|
|
32
|
+
* app.use(errorHandler({
|
|
33
|
+
* isDev: false,
|
|
34
|
+
* logger: arcis.logger()
|
|
35
|
+
* }));
|
|
36
|
+
*/
|
|
37
|
+
export declare function errorHandler(options?: ErrorHandlerOptions | boolean): (err: Error, req: Request, res: Response, next: NextFunction) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Alias for errorHandler
|
|
40
|
+
* @see errorHandler
|
|
41
|
+
*/
|
|
42
|
+
export declare const createErrorHandler: typeof errorHandler;
|
|
43
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,mBAAmB,EAAa,MAAM,eAAe,CAAC;AAyBpE;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAmB,GAAG,OAAe,GAC7C,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CA2DvE;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,qBAAe,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/headers
|
|
3
|
+
* Security headers middleware
|
|
4
|
+
*/
|
|
5
|
+
import type { RequestHandler } from 'express';
|
|
6
|
+
import type { HeaderOptions } from '../core/types';
|
|
7
|
+
/**
|
|
8
|
+
* Create Express middleware for security headers.
|
|
9
|
+
* Sets CSP, HSTS, X-Frame-Options, and other security headers.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Header configuration
|
|
12
|
+
* @returns Express middleware
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* app.use(createHeaders());
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* app.use(createHeaders({
|
|
19
|
+
* frameOptions: 'SAMEORIGIN',
|
|
20
|
+
* contentSecurityPolicy: "default-src 'self'"
|
|
21
|
+
* }));
|
|
22
|
+
*/
|
|
23
|
+
export declare function createHeaders(options?: HeaderOptions): RequestHandler;
|
|
24
|
+
/**
|
|
25
|
+
* Alias for createHeaders
|
|
26
|
+
* @see createHeaders
|
|
27
|
+
*/
|
|
28
|
+
export declare const securityHeaders: typeof createHeaders;
|
|
29
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/middleware/headers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,eAAe,CAAC;AAEhE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,cAAc,CAwHzE;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,sBAAgB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware/hpp
|
|
3
|
+
* HTTP Parameter Pollution (HPP) protection middleware
|
|
4
|
+
*
|
|
5
|
+
* Normalizes duplicate query and body parameters to their last value,
|
|
6
|
+
* preventing attackers from bypassing validation by repeating parameters.
|
|
7
|
+
*
|
|
8
|
+
* Attack example:
|
|
9
|
+
* GET /search?role=user&role=admin
|
|
10
|
+
* Without HPP: req.query.role = ['user', 'admin']
|
|
11
|
+
* With HPP: req.query.role = 'admin' (last value wins)
|
|
12
|
+
*
|
|
13
|
+
* Originals are preserved in req.queryPolluted / req.bodyPolluted
|
|
14
|
+
* for logging or auditing without blocking the request.
|
|
15
|
+
*/
|
|
16
|
+
import type { RequestHandler } from 'express';
|
|
17
|
+
/** HPP protection configuration */
|
|
18
|
+
export interface HppOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Parameters that legitimately accept arrays and should not be normalized.
|
|
21
|
+
* Example: ['tags', 'ids', 'filter']
|
|
22
|
+
*/
|
|
23
|
+
whitelist?: string[];
|
|
24
|
+
/** Normalize duplicate query string parameters. Default: true */
|
|
25
|
+
checkQuery?: boolean;
|
|
26
|
+
/** Normalize duplicate body parameters. Default: true */
|
|
27
|
+
checkBody?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* HTTP Parameter Pollution protection middleware.
|
|
31
|
+
*
|
|
32
|
+
* Normalizes duplicate query/body parameters to a single value (last wins).
|
|
33
|
+
* Whitelisted parameters are allowed to remain as arrays.
|
|
34
|
+
*
|
|
35
|
+
* @param options - HPP configuration
|
|
36
|
+
* @returns Express middleware
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Basic — normalize all duplicates
|
|
40
|
+
* app.use(hpp());
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Allow arrays for specific params (e.g., tag filters, IDs)
|
|
44
|
+
* app.use(hpp({ whitelist: ['tags', 'ids'] }));
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // Inspect what was removed (for logging)
|
|
48
|
+
* app.use((req, res, next) => {
|
|
49
|
+
* const polluted = (req as any).queryPolluted;
|
|
50
|
+
* if (Object.keys(polluted).length) logger.warn('HPP detected', polluted);
|
|
51
|
+
* next();
|
|
52
|
+
* });
|
|
53
|
+
*/
|
|
54
|
+
export declare function hpp(options?: HppOptions): RequestHandler;
|
|
55
|
+
export declare const createHpp: typeof hpp;
|
|
56
|
+
//# sourceMappingURL=hpp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hpp.d.ts","sourceRoot":"","sources":["../../src/middleware/hpp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,cAAc,CAwD5D;AAED,eAAO,MAAM,SAAS,YAAM,CAAC"}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/middleware
|
|
3
|
+
* All middleware for Arcis
|
|
4
|
+
*/
|
|
5
|
+
export { arcis, arcisFunction } from './main';
|
|
6
|
+
export { default } from './main';
|
|
7
|
+
export { createRateLimiter, rateLimit } from './rate-limit';
|
|
8
|
+
export { createSlidingWindowLimiter } from './rate-limit-sliding';
|
|
9
|
+
export { createTokenBucketLimiter } from './rate-limit-token';
|
|
10
|
+
export { createHeaders, securityHeaders } from './headers';
|
|
11
|
+
export { errorHandler, createErrorHandler } from './error-handler';
|
|
12
|
+
export { safeCors, createCors } from './cors';
|
|
13
|
+
export { secureCookieDefaults, createSecureCookies, enforceSecureCookie } from './cookies';
|
|
14
|
+
export { botProtection, detectBot } from './bot-detection';
|
|
15
|
+
export { csrfProtection, createCsrf, generateCsrfToken, validateCsrfToken } from './csrf';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/middleware/index.js
CHANGED
|
@@ -1606,12 +1606,14 @@ function getRequestToken(req, headerName, fieldName) {
|
|
|
1606
1606
|
return void 0;
|
|
1607
1607
|
}
|
|
1608
1608
|
function csrfProtection(options = {}) {
|
|
1609
|
-
const
|
|
1609
|
+
const baseCookieName = options.cookieName ?? DEFAULTS.cookieName;
|
|
1610
|
+
const cookieName = options.useHostPrefix ? `__Host-${baseCookieName}` : baseCookieName;
|
|
1610
1611
|
const headerName = options.headerName ?? DEFAULTS.headerName;
|
|
1611
1612
|
const fieldName = options.fieldName ?? DEFAULTS.fieldName;
|
|
1612
1613
|
const tokenLength = options.tokenLength ?? DEFAULTS.tokenLength;
|
|
1613
1614
|
const protectedMethods = options.protectedMethods ?? [...DEFAULTS.protectedMethods];
|
|
1614
1615
|
const excludePaths = options.excludePaths ?? [];
|
|
1616
|
+
const skipCsrf = options.skipCsrf;
|
|
1615
1617
|
const isProduction = process.env.NODE_ENV === "production";
|
|
1616
1618
|
const cookieOpts = {
|
|
1617
1619
|
path: options.cookie?.path ?? "/",
|
|
@@ -1631,6 +1633,9 @@ function csrfProtection(options = {}) {
|
|
|
1631
1633
|
const protectedSet = new Set(protectedMethods.map((m) => m.toUpperCase()));
|
|
1632
1634
|
return (req, res, next) => {
|
|
1633
1635
|
const method = req.method.toUpperCase();
|
|
1636
|
+
if (skipCsrf && skipCsrf(req)) {
|
|
1637
|
+
return next();
|
|
1638
|
+
}
|
|
1634
1639
|
const requestPath = req.path || req.url;
|
|
1635
1640
|
if (excludePaths.some((p) => requestPath === p || requestPath.startsWith(p + "/"))) {
|
|
1636
1641
|
return next();
|