@arcis/node 1.3.0 → 1.4.2

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 (139) hide show
  1. package/README.md +1 -1
  2. package/dist/core/{index.d.mts → constants.d.ts} +21 -70
  3. package/dist/core/constants.d.ts.map +1 -0
  4. package/dist/core/errors.d.ts +53 -0
  5. package/dist/core/errors.d.ts.map +1 -0
  6. package/dist/core/index.d.ts +6 -168
  7. package/dist/core/index.d.ts.map +1 -0
  8. package/dist/core/index.js +11 -3
  9. package/dist/core/index.js.map +1 -1
  10. package/dist/core/index.mjs +11 -3
  11. package/dist/core/index.mjs.map +1 -1
  12. package/dist/{types-BOkx5YJc.d.mts → core/types.d.ts} +27 -30
  13. package/dist/core/types.d.ts.map +1 -0
  14. package/dist/index.d.ts +71 -166
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +182 -48
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +182 -50
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/logging/index.d.ts +4 -36
  21. package/dist/logging/index.d.ts.map +1 -0
  22. package/dist/logging/index.js.map +1 -1
  23. package/dist/logging/index.mjs.map +1 -1
  24. package/dist/logging/{index.d.mts → redactor.d.ts} +5 -9
  25. package/dist/logging/redactor.d.ts.map +1 -0
  26. package/dist/middleware/bot-detection.d.ts +86 -0
  27. package/dist/middleware/bot-detection.d.ts.map +1 -0
  28. package/dist/middleware/cookies.d.ts +48 -0
  29. package/dist/middleware/cookies.d.ts.map +1 -0
  30. package/dist/middleware/cors.d.ts +65 -0
  31. package/dist/middleware/cors.d.ts.map +1 -0
  32. package/dist/middleware/csrf.d.ts +109 -0
  33. package/dist/middleware/csrf.d.ts.map +1 -0
  34. package/dist/middleware/error-handler.d.ts +43 -0
  35. package/dist/middleware/error-handler.d.ts.map +1 -0
  36. package/dist/middleware/headers.d.ts +29 -0
  37. package/dist/middleware/headers.d.ts.map +1 -0
  38. package/dist/middleware/hpp.d.ts +56 -0
  39. package/dist/middleware/hpp.d.ts.map +1 -0
  40. package/dist/middleware/index.d.ts +16 -3
  41. package/dist/middleware/index.d.ts.map +1 -0
  42. package/dist/middleware/index.js +68 -31
  43. package/dist/middleware/index.js.map +1 -1
  44. package/dist/middleware/index.mjs +69 -32
  45. package/dist/middleware/index.mjs.map +1 -1
  46. package/dist/middleware/main.d.ts +40 -0
  47. package/dist/middleware/main.d.ts.map +1 -0
  48. package/dist/middleware/rate-limit-sliding.d.ts +46 -0
  49. package/dist/middleware/rate-limit-sliding.d.ts.map +1 -0
  50. package/dist/middleware/rate-limit-token.d.ts +51 -0
  51. package/dist/middleware/rate-limit-token.d.ts.map +1 -0
  52. package/dist/middleware/rate-limit.d.ts +34 -0
  53. package/dist/middleware/rate-limit.d.ts.map +1 -0
  54. package/dist/sanitizers/command.d.ts +28 -0
  55. package/dist/sanitizers/command.d.ts.map +1 -0
  56. package/dist/sanitizers/encode.d.ts +46 -0
  57. package/dist/sanitizers/encode.d.ts.map +1 -0
  58. package/dist/sanitizers/headers.d.ts +46 -0
  59. package/dist/sanitizers/headers.d.ts.map +1 -0
  60. package/dist/sanitizers/index.d.ts +18 -22
  61. package/dist/sanitizers/index.d.ts.map +1 -0
  62. package/dist/sanitizers/index.js +90 -32
  63. package/dist/sanitizers/index.js.map +1 -1
  64. package/dist/sanitizers/index.mjs +88 -33
  65. package/dist/sanitizers/index.mjs.map +1 -1
  66. package/dist/sanitizers/jsonp.d.ts +34 -0
  67. package/dist/sanitizers/jsonp.d.ts.map +1 -0
  68. package/dist/sanitizers/ldap.d.ts +42 -0
  69. package/dist/sanitizers/ldap.d.ts.map +1 -0
  70. package/dist/sanitizers/nosql.d.ts +31 -0
  71. package/dist/sanitizers/nosql.d.ts.map +1 -0
  72. package/dist/sanitizers/path.d.ts +28 -0
  73. package/dist/sanitizers/path.d.ts.map +1 -0
  74. package/dist/sanitizers/pii.d.ts +80 -0
  75. package/dist/sanitizers/pii.d.ts.map +1 -0
  76. package/dist/sanitizers/prototype.d.ts +34 -0
  77. package/dist/sanitizers/prototype.d.ts.map +1 -0
  78. package/dist/sanitizers/sanitize.d.ts +51 -0
  79. package/dist/sanitizers/sanitize.d.ts.map +1 -0
  80. package/dist/sanitizers/sql.d.ts +28 -0
  81. package/dist/sanitizers/sql.d.ts.map +1 -0
  82. package/dist/sanitizers/ssti.d.ts +20 -0
  83. package/dist/sanitizers/ssti.d.ts.map +1 -0
  84. package/dist/sanitizers/utils.d.ts +19 -0
  85. package/dist/sanitizers/utils.d.ts.map +1 -0
  86. package/dist/sanitizers/xss.d.ts +35 -0
  87. package/dist/sanitizers/xss.d.ts.map +1 -0
  88. package/dist/sanitizers/xxe.d.ts +20 -0
  89. package/dist/sanitizers/xxe.d.ts.map +1 -0
  90. package/dist/stores/index.d.ts +6 -104
  91. package/dist/stores/index.d.ts.map +1 -0
  92. package/dist/stores/index.js +21 -1
  93. package/dist/stores/index.js.map +1 -1
  94. package/dist/stores/index.mjs +21 -1
  95. package/dist/stores/index.mjs.map +1 -1
  96. package/dist/stores/memory.d.ts +29 -0
  97. package/dist/stores/memory.d.ts.map +1 -0
  98. package/dist/stores/{index.d.mts → redis.d.ts} +6 -45
  99. package/dist/stores/redis.d.ts.map +1 -0
  100. package/dist/utils/duration.d.ts +34 -0
  101. package/dist/utils/duration.d.ts.map +1 -0
  102. package/dist/utils/fingerprint.d.ts +64 -0
  103. package/dist/utils/fingerprint.d.ts.map +1 -0
  104. package/dist/utils/index.d.ts +10 -0
  105. package/dist/utils/index.d.ts.map +1 -0
  106. package/dist/utils/index.js +188 -0
  107. package/dist/utils/index.js.map +1 -0
  108. package/dist/utils/index.mjs +182 -0
  109. package/dist/utils/index.mjs.map +1 -0
  110. package/dist/utils/ip.d.ts +70 -0
  111. package/dist/utils/ip.d.ts.map +1 -0
  112. package/dist/validation/email.d.ts +82 -0
  113. package/dist/validation/email.d.ts.map +1 -0
  114. package/dist/validation/file.d.ts +90 -0
  115. package/dist/validation/file.d.ts.map +1 -0
  116. package/dist/validation/index.d.ts +10 -3
  117. package/dist/validation/index.d.ts.map +1 -0
  118. package/dist/validation/index.js +38 -21
  119. package/dist/validation/index.js.map +1 -1
  120. package/dist/validation/index.mjs +38 -21
  121. package/dist/validation/index.mjs.map +1 -1
  122. package/dist/validation/redirect.d.ts +64 -0
  123. package/dist/validation/redirect.d.ts.map +1 -0
  124. package/dist/validation/schema.d.ts +36 -0
  125. package/dist/validation/schema.d.ts.map +1 -0
  126. package/dist/validation/url.d.ts +65 -0
  127. package/dist/validation/url.d.ts.map +1 -0
  128. package/package.json +8 -6
  129. package/dist/encode-CrQCGlBq.d.mts +0 -484
  130. package/dist/encode-jl9sOwmA.d.ts +0 -484
  131. package/dist/index-BAhgn9V2.d.ts +0 -532
  132. package/dist/index-BGNKspqH.d.ts +0 -340
  133. package/dist/index-Cd02z-0j.d.mts +0 -340
  134. package/dist/index-DgJtWMSj.d.mts +0 -532
  135. package/dist/index.d.mts +0 -175
  136. package/dist/middleware/index.d.mts +0 -3
  137. package/dist/sanitizers/index.d.mts +0 -24
  138. package/dist/types-BOkx5YJc.d.ts +0 -279
  139. package/dist/validation/index.d.mts +0 -3
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @module @arcis/node/validation/redirect
3
+ * Open Redirect prevention
4
+ *
5
+ * Prevents attackers from using your app to redirect users to malicious sites
6
+ * via manipulated query parameters like ?returnUrl=http://evil.com
7
+ *
8
+ * @example
9
+ * import { validateRedirect, isRedirectSafe } from '@arcis/node';
10
+ *
11
+ * // Block open redirects
12
+ * validateRedirect('http://evil.com') // { safe: false, reason: 'absolute URL not in allowed hosts' }
13
+ * validateRedirect('//evil.com') // { safe: false, reason: 'protocol-relative URL not in allowed hosts' }
14
+ * validateRedirect('javascript:alert(1)') // { safe: false, reason: 'dangerous protocol: javascript:' }
15
+ *
16
+ * // Allow safe redirects
17
+ * validateRedirect('/dashboard') // { safe: true }
18
+ * validateRedirect('/users?page=2') // { safe: true }
19
+ * validateRedirect('https://myapp.com/home', { allowedHosts: ['myapp.com'] }) // { safe: true }
20
+ */
21
+ /** Options for redirect validation */
22
+ export interface ValidateRedirectOptions {
23
+ /** Hostnames that are allowed for absolute URL redirects */
24
+ allowedHosts?: string[];
25
+ /** Allow protocol-relative URLs (//example.com). Default: false */
26
+ allowProtocolRelative?: boolean;
27
+ /** Allowed protocols for absolute URLs. Default: ['http:', 'https:'] */
28
+ allowedProtocols?: string[];
29
+ }
30
+ /** Result of redirect validation */
31
+ export interface ValidateRedirectResult {
32
+ /** Whether the redirect URL is safe */
33
+ safe: boolean;
34
+ /** Reason the redirect was blocked (only set when safe=false) */
35
+ reason?: string;
36
+ }
37
+ /**
38
+ * Validate a redirect URL to prevent open redirect attacks.
39
+ *
40
+ * Safe redirects:
41
+ * - Relative paths: /dashboard, /users?page=2, ../settings
42
+ * - Absolute URLs to allowed hosts (when configured)
43
+ *
44
+ * Blocked redirects:
45
+ * - Absolute URLs to unknown hosts
46
+ * - Protocol-relative URLs (//evil.com)
47
+ * - javascript:, data:, vbscript:, blob: protocols
48
+ * - Backslash-prefixed paths (\\evil.com — browser treats as //)
49
+ * - URLs with control characters that could disguise the target
50
+ *
51
+ * @param url - The redirect target URL to validate
52
+ * @param options - Validation options
53
+ * @returns Validation result with safe flag and optional reason
54
+ */
55
+ export declare function validateRedirect(url: string, options?: ValidateRedirectOptions): ValidateRedirectResult;
56
+ /**
57
+ * Convenience wrapper that returns true/false.
58
+ *
59
+ * @param url - The redirect URL to check
60
+ * @param options - Validation options
61
+ * @returns true if the redirect is safe
62
+ */
63
+ export declare function isRedirectSafe(url: string, options?: ValidateRedirectOptions): boolean;
64
+ //# sourceMappingURL=redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/validation/redirect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,sCAAsC;AACtC,MAAM,WAAW,uBAAuB;IACtC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,oCAAoC;AACpC,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAqExB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAE1F"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @module @arcis/node/validation/schema
3
+ * Request validation middleware
4
+ */
5
+ import type { RequestHandler } from 'express';
6
+ import type { ValidationSchema } from '../core/types';
7
+ /**
8
+ * Create Express middleware for request validation.
9
+ * Prevents mass assignment by only allowing fields defined in the schema.
10
+ *
11
+ * @param schema - Validation schema defining expected fields
12
+ * @param source - Request property to validate ('body', 'query', or 'params')
13
+ * @returns Express middleware
14
+ *
15
+ * @example
16
+ * app.post('/users', validate({
17
+ * email: { type: 'email', required: true },
18
+ * name: { type: 'string', min: 2, max: 50 },
19
+ * age: { type: 'number', min: 0, max: 150 },
20
+ * role: { type: 'string', enum: ['user', 'admin'] }
21
+ * }), handler);
22
+ *
23
+ * @example
24
+ * // Validate query params
25
+ * app.get('/search', validate({
26
+ * q: { type: 'string', required: true, min: 1 },
27
+ * page: { type: 'number', min: 1 }
28
+ * }, 'query'), handler);
29
+ */
30
+ export declare function validate(schema: ValidationSchema, source?: 'body' | 'query' | 'params'): RequestHandler;
31
+ /**
32
+ * Alias for validate
33
+ * @see validate
34
+ */
35
+ export declare const createValidator: typeof validate;
36
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/validation/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAE/E,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,eAAe,CAAC;AAGtE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,gBAAgB,EACxB,MAAM,GAAE,MAAM,GAAG,OAAO,GAAG,QAAiB,GAC3C,cAAc,CA0BhB;AAoKD;;;GAGG;AACH,eAAO,MAAM,eAAe,iBAAW,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @module @arcis/node/validation/url
3
+ * SSRF (Server-Side Request Forgery) prevention
4
+ *
5
+ * Validates URLs to ensure they don't target private/internal networks,
6
+ * localhost, cloud metadata endpoints, or use dangerous protocols.
7
+ *
8
+ * @example
9
+ * import { validateUrl } from '@arcis/node';
10
+ *
11
+ * // Block SSRF attempts
12
+ * validateUrl('http://169.254.169.254/latest/meta-data/') // { safe: false, reason: 'link-local address' }
13
+ * validateUrl('http://10.0.0.1/admin') // { safe: false, reason: 'private address (10.0.0.0/8)' }
14
+ * validateUrl('http://localhost/secret') // { safe: false, reason: 'loopback address' }
15
+ * validateUrl('file:///etc/passwd') // { safe: false, reason: 'disallowed protocol: file:' }
16
+ *
17
+ * // Allow safe URLs
18
+ * validateUrl('https://api.example.com/data') // { safe: true }
19
+ */
20
+ /** Options for URL validation */
21
+ export interface ValidateUrlOptions {
22
+ /** Allowed protocols. Default: ['http:', 'https:'] */
23
+ allowedProtocols?: string[];
24
+ /** Additional hostnames to block (e.g., internal service names) */
25
+ blockedHosts?: string[];
26
+ /** Additional hostnames to always allow (bypass IP checks) */
27
+ allowedHosts?: string[];
28
+ /** Allow localhost/loopback. Default: false */
29
+ allowLocalhost?: boolean;
30
+ /** Allow private/internal IPs. Default: false */
31
+ allowPrivate?: boolean;
32
+ }
33
+ /** Result of URL validation */
34
+ export interface ValidateUrlResult {
35
+ /** Whether the URL is safe to fetch */
36
+ safe: boolean;
37
+ /** Reason the URL was blocked (only set when safe=false) */
38
+ reason?: string;
39
+ }
40
+ /**
41
+ * Validate a URL for SSRF safety.
42
+ *
43
+ * Checks:
44
+ * 1. Valid URL format
45
+ * 2. Allowed protocol (default: http, https only)
46
+ * 3. Not localhost/loopback (127.x.x.x, ::1, localhost)
47
+ * 4. Not private IP (10.x, 172.16-31.x, 192.168.x)
48
+ * 5. Not link-local (169.254.x.x — includes AWS/GCP/Azure metadata)
49
+ * 6. Not blocked hostname
50
+ * 7. No credentials in URL (user:pass@host)
51
+ *
52
+ * @param url - The URL string to validate
53
+ * @param options - Validation options
54
+ * @returns Validation result with safe flag and optional reason
55
+ */
56
+ export declare function validateUrl(url: string, options?: ValidateUrlOptions): ValidateUrlResult;
57
+ /**
58
+ * Convenience wrapper that returns true/false.
59
+ *
60
+ * @param url - The URL to check
61
+ * @param options - Validation options
62
+ * @returns true if the URL is safe to fetch
63
+ */
64
+ export declare function isUrlSafe(url: string, options?: ValidateUrlOptions): boolean;
65
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/validation/url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iCAAiC;AACjC,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,+BAA+B;AAC/B,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CAuF5F;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAEhF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcis/node",
3
- "version": "1.3.0",
4
- "description": "One-line security middleware for Node.js apps.",
3
+ "version": "1.4.2",
4
+ "description": "Zero-dependency security middleware for Node.js. Protects against XSS, SQL injection, CSRF, SSRF, HPP, rate limiting, bot detection, and 15+ more attack types. Supply chain attack scanner included.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -51,14 +51,14 @@
51
51
  "dist"
52
52
  ],
53
53
  "scripts": {
54
- "build": "tsup",
54
+ "build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap",
55
55
  "dev": "tsup --watch",
56
56
  "test": "vitest",
57
57
  "test:unit": "vitest run tests/index.test.ts",
58
58
  "test:integration": "vitest run tests/integration.test.ts",
59
59
  "test:conformance": "vitest run tests/conformance.test.ts",
60
60
  "test:coverage": "vitest --coverage",
61
- "lint": "eslint src --ext .ts",
61
+ "lint": "eslint src",
62
62
  "typecheck": "tsc --noEmit",
63
63
  "prepublishOnly": "npm run build"
64
64
  },
@@ -94,10 +94,12 @@
94
94
  "devDependencies": {
95
95
  "@types/express": "^5.0.6",
96
96
  "@types/node": "^25.5.0",
97
- "eslint": "^8.55.0",
97
+ "@typescript-eslint/eslint-plugin": "^8.58.0",
98
+ "@typescript-eslint/parser": "^8.58.0",
99
+ "eslint": "^10.1.0",
98
100
  "express": "^5.2.1",
99
101
  "tsup": "^8.0.1",
100
- "typescript": "^5.3.2",
102
+ "typescript": "^6.0.2",
101
103
  "vitest": "^4.1.0"
102
104
  },
103
105
  "repository": {