@arcis/node 1.0.0 → 1.2.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/README.md +156 -222
- package/dist/core/index.d.mts +4 -4
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +13 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +13 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/index-A-m-pPeW.d.mts +340 -0
- package/dist/index-CgK94hY_.d.mts +532 -0
- package/dist/index-Co5kPRZz.d.ts +340 -0
- package/dist/index-D_bdJcF0.d.ts +532 -0
- package/dist/index.d.mts +144 -108
- package/dist/index.d.ts +144 -108
- package/dist/index.js +1541 -211
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1515 -212
- package/dist/index.mjs.map +1 -1
- package/dist/logging/index.d.mts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.js +12 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/index.mjs +12 -1
- package/dist/logging/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +2 -2
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +524 -4
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +517 -5
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/{headers-DBQedhrb.d.mts → pii-CXcHMlnX.d.mts} +156 -2
- package/dist/{headers-BJq2OA0i.d.ts → pii-DhNpl7M3.d.ts} +156 -2
- package/dist/sanitizers/index.d.mts +2 -2
- package/dist/sanitizers/index.d.ts +2 -2
- package/dist/sanitizers/index.js +331 -3
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +321 -4
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/stores/index.d.mts +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js.map +1 -1
- package/dist/stores/index.mjs.map +1 -1
- package/dist/{types-BOdL3ZWo.d.mts → types-CsOFHoD9.d.mts} +6 -1
- package/dist/{types-BOdL3ZWo.d.ts → types-CsOFHoD9.d.ts} +6 -1
- package/dist/validation/index.d.mts +2 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +504 -2
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/index.mjs +498 -3
- package/dist/validation/index.mjs.map +1 -1
- package/package.json +114 -109
- package/dist/index-BgHPM7LC.d.ts +0 -129
- package/dist/index-BpT7flAQ.d.ts +0 -255
- package/dist/index-JaFOUKyK.d.mts +0 -255
- package/dist/index-nAgXexwD.d.mts +0 -129
package/README.md
CHANGED
|
@@ -1,222 +1,156 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
from arcis
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
## What It Does
|
|
158
|
-
|
|
159
|
-
One `app.use(arcis())` gives you all 15 categories above. Or use individual functions for fine-grained control:
|
|
160
|
-
|
|
161
|
-
- **Sanitize** — `sanitizeString()`, `sanitizeObject()` strip dangerous patterns
|
|
162
|
-
- **Detect** — `detectXss()`, `detectSql()`, `detectHeaderInjection()` flag threats without modifying input
|
|
163
|
-
- **Validate** — `validateUrl()` blocks SSRF, `validateRedirect()` blocks open redirects
|
|
164
|
-
- **Protect** — rate limiting, security headers, safe logging, error handling
|
|
165
|
-
|
|
166
|
-
## Architecture
|
|
167
|
-
|
|
168
|
-
Arcis separates **core security logic** from **framework adapters**:
|
|
169
|
-
|
|
170
|
-
```
|
|
171
|
-
@arcis/node
|
|
172
|
-
├── Core (framework-agnostic)
|
|
173
|
-
│ ├── sanitizeString / sanitizeObject — clean any input
|
|
174
|
-
│ ├── detectXss / detectSql / ... — threat detection
|
|
175
|
-
│ ├── createSafeLogger / createRedactor — safe logging
|
|
176
|
-
│ ├── MemoryStore / RedisStore — rate limit backends
|
|
177
|
-
│ └── Error classes and constants
|
|
178
|
-
│
|
|
179
|
-
└── Adapters (framework-specific)
|
|
180
|
-
└── Express middleware (arcis(), arcis.sanitize(), arcis.rateLimit(), ...)
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
The core functions are pure — no `req`, `res`, or `next`. They take values in and return values out. This means they work with Express, Fastify, Koa, Hono, Nest, raw `http.createServer`, Bun, Deno, serverless functions, or anything else.
|
|
184
|
-
|
|
185
|
-
Subpath imports are available for tree-shaking:
|
|
186
|
-
|
|
187
|
-
```js
|
|
188
|
-
import { sanitizeString } from '@arcis/node/sanitizers';
|
|
189
|
-
import { createSafeLogger } from '@arcis/node/logging';
|
|
190
|
-
import { MemoryStore } from '@arcis/node/stores';
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## Supported Frameworks
|
|
194
|
-
|
|
195
|
-
| SDK | Built-in Adapters | Core Functions | Status |
|
|
196
|
-
|-----|-------------------|----------------|--------|
|
|
197
|
-
| Node.js | Express | Work with any framework | Stable |
|
|
198
|
-
| Python | Flask, FastAPI, Django | Work standalone | Stable |
|
|
199
|
-
| Go | net/http, Gin, Echo | Work standalone | Stable |
|
|
200
|
-
| Java | Spring Boot | — | Planned |
|
|
201
|
-
| C# | ASP.NET Core | — | Planned |
|
|
202
|
-
|
|
203
|
-
**Node.js roadmap:** Built-in adapters for Fastify, Koa, and Hono are planned. The core functions already work with these frameworks — you just wire a short middleware wrapper (see examples above).
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
## How It Works
|
|
207
|
-
|
|
208
|
-
All SDKs load security patterns from a shared `patterns.json` at runtime. A shared spec (`API_SPEC.md`) and test vectors (`TEST_VECTORS.json`) enforce identical behavior across languages.
|
|
209
|
-
|
|
210
|
-
## Documentation
|
|
211
|
-
|
|
212
|
-
Detailed configuration, API reference, Redis setup, granular middleware usage, and architecture docs are in the [Wiki](https://github.com/Gagancm/arcis/wiki).
|
|
213
|
-
|
|
214
|
-
## Contributing
|
|
215
|
-
|
|
216
|
-
1. All changes must pass existing tests
|
|
217
|
-
2. New features require test cases aligned with `spec/TEST_VECTORS.json`
|
|
218
|
-
3. Pattern changes in `packages/core/patterns.json` must be reflected in all SDKs
|
|
219
|
-
|
|
220
|
-
## License
|
|
221
|
-
|
|
222
|
-
MIT
|
|
1
|
+
# @arcis/node
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@arcis/node)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://github.com/Gagancm/arcis/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
**One-line security middleware for Node.js.**
|
|
8
|
+
|
|
9
|
+
Part of the [Arcis](https://github.com/Gagancm/arcis) ecosystem with implementations for Node.js, Python, and Go.
|
|
10
|
+
|
|
11
|
+
**17 attack vectors handled. 970+ tests. Zero dependencies.**
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @arcis/node
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### With Express (built-in adapter)
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import { arcis } from '@arcis/node';
|
|
25
|
+
|
|
26
|
+
app.use(arcis());
|
|
27
|
+
// That's it. Sanitization, rate limiting, and security headers are on.
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### With any framework (Fastify, Koa, Hono, etc.)
|
|
31
|
+
|
|
32
|
+
The core sanitization, validation, and logging functions have zero framework dependencies. Use them directly in any Node.js project:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import {
|
|
36
|
+
sanitizeString,
|
|
37
|
+
sanitizeObject,
|
|
38
|
+
detectXss,
|
|
39
|
+
detectSql,
|
|
40
|
+
detectCommandInjection,
|
|
41
|
+
detectPathTraversal,
|
|
42
|
+
createSafeLogger,
|
|
43
|
+
createRedactor,
|
|
44
|
+
} from '@arcis/node';
|
|
45
|
+
|
|
46
|
+
// Sanitize user input — works anywhere
|
|
47
|
+
const clean = sanitizeString(userInput);
|
|
48
|
+
const cleanBody = sanitizeObject(requestBody);
|
|
49
|
+
|
|
50
|
+
// Detect threats without sanitizing
|
|
51
|
+
if (detectXss(value)) { /* reject */ }
|
|
52
|
+
if (detectSql(value)) { /* reject */ }
|
|
53
|
+
|
|
54
|
+
// Safe logging — no framework needed
|
|
55
|
+
const logger = createSafeLogger();
|
|
56
|
+
logger.info('User login', { email, password: 'will-be-redacted' });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Writing your own middleware is straightforward.** Here's a Fastify example:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
import { sanitizeObject } from '@arcis/node';
|
|
63
|
+
|
|
64
|
+
fastify.addHook('preHandler', async (request, reply) => {
|
|
65
|
+
if (request.body) request.body = sanitizeObject(request.body);
|
|
66
|
+
if (request.query) request.query = sanitizeObject(request.query);
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Koa:
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
import { sanitizeObject } from '@arcis/node';
|
|
74
|
+
|
|
75
|
+
app.use(async (ctx, next) => {
|
|
76
|
+
if (ctx.request.body) ctx.request.body = sanitizeObject(ctx.request.body);
|
|
77
|
+
if (ctx.query) ctx.query = sanitizeObject(ctx.query);
|
|
78
|
+
await next();
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Hono:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
import { sanitizeObject } from '@arcis/node';
|
|
86
|
+
|
|
87
|
+
app.use('*', async (c, next) => {
|
|
88
|
+
const body = await c.req.json().catch(() => null);
|
|
89
|
+
if (body) c.set('sanitizedBody', sanitizeObject(body));
|
|
90
|
+
await next();
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## What It Protects Against
|
|
95
|
+
|
|
96
|
+
| Category | What it stops |
|
|
97
|
+
|----------|--------------|
|
|
98
|
+
| XSS | Script injection, event handlers, `javascript:` URIs, SVG/iframe payloads |
|
|
99
|
+
| SQL Injection | Keywords, boolean logic, comments, time-based blind (`SLEEP`, `BENCHMARK`) |
|
|
100
|
+
| NoSQL Injection | MongoDB operators (`$gt`, `$where`, `$regex`, 25+ blocked operators) |
|
|
101
|
+
| Command Injection | Shell metacharacters, dangerous commands, redirections |
|
|
102
|
+
| Path Traversal | `../`, encoded variants (`%2e%2e`), null byte injection |
|
|
103
|
+
| Prototype Pollution | `__proto__`, `constructor`, `__defineGetter__`, 7 keys blocked (case-insensitive) |
|
|
104
|
+
| HTTP Header Injection | CRLF injection, response splitting, null bytes |
|
|
105
|
+
| SSRF | Private IPs, loopback, link-local, cloud metadata, dangerous protocols |
|
|
106
|
+
| Open Redirect | Absolute URLs, `javascript:`, protocol-relative, backslash/control char bypass |
|
|
107
|
+
| Error Leakage | Stack traces, DB errors, connection strings, internal IPs scrubbed in production |
|
|
108
|
+
| CORS Misconfiguration | Whitelist-based origins, `null` origin blocked, `Vary: Origin` enforced |
|
|
109
|
+
| Cookie Security | HttpOnly, Secure, SameSite enforced on all cookies |
|
|
110
|
+
| Rate Limiting | Per-IP, sliding window, token bucket, in-memory or Redis, `X-RateLimit-*` headers |
|
|
111
|
+
| Bot Detection | 80+ patterns, 7 categories (crawlers, scrapers, AI bots, etc.), behavioral signals |
|
|
112
|
+
| CSRF | Double-submit cookie, token generation and validation |
|
|
113
|
+
| Security Headers | CSP, HSTS, X-Frame-Options, 10 headers out of the box |
|
|
114
|
+
| Input Validation | Type checking, ranges, enums, email (disposable blocklist, typo suggestions, MX verify), mass assignment prevention |
|
|
115
|
+
|
|
116
|
+
## Architecture
|
|
117
|
+
|
|
118
|
+
Arcis separates **core security logic** from **framework adapters**:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
@arcis/node
|
|
122
|
+
├── Core (framework-agnostic)
|
|
123
|
+
│ ├── sanitizeString / sanitizeObject — clean any input
|
|
124
|
+
│ ├── detectXss / detectSql / ... — threat detection
|
|
125
|
+
│ ├── createSafeLogger / createRedactor — safe logging
|
|
126
|
+
│ ├── MemoryStore / RedisStore — rate limit backends
|
|
127
|
+
│ └── Error classes and constants
|
|
128
|
+
│
|
|
129
|
+
└── Adapters (framework-specific)
|
|
130
|
+
└── Express middleware (arcis(), arcis.sanitize(), arcis.rateLimit(), ...)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The core functions are pure — no `req`, `res`, or `next`. They take values in and return values out. This means they work with Express, Fastify, Koa, Hono, Nest, raw `http.createServer`, Bun, Deno, serverless functions, or anything else.
|
|
134
|
+
|
|
135
|
+
Subpath imports are available for tree-shaking:
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
import { sanitizeString } from '@arcis/node/sanitizers';
|
|
139
|
+
import { createSafeLogger } from '@arcis/node/logging';
|
|
140
|
+
import { MemoryStore } from '@arcis/node/stores';
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Documentation
|
|
144
|
+
|
|
145
|
+
Detailed configuration, API reference, Redis setup, and architecture docs are in the [Wiki](https://github.com/Gagancm/arcis/wiki).
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
148
|
+
|
|
149
|
+
1. Fork the repo and create your branch from `nwl` (the active development branch)
|
|
150
|
+
2. All PRs target `nwl` — `main` is release-only
|
|
151
|
+
3. All changes must pass existing tests
|
|
152
|
+
4. New features require test cases aligned with `spec/TEST_VECTORS.json`
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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.mjs';
|
|
2
2
|
import 'express';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -98,9 +98,9 @@ declare const HEADERS: {
|
|
|
98
98
|
* Must stay in sync with XSS_REMOVE_PATTERNS below.
|
|
99
99
|
*/
|
|
100
100
|
declare const XSS_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
101
|
-
declare const SQL_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
102
|
-
declare const PATH_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
103
|
-
declare const COMMAND_PATTERNS: readonly [RegExp, RegExp];
|
|
101
|
+
declare const SQL_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
102
|
+
declare const PATH_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
103
|
+
declare const COMMAND_PATTERNS: readonly [RegExp, RegExp, RegExp];
|
|
104
104
|
/**
|
|
105
105
|
* Prototype pollution keys to block.
|
|
106
106
|
* Stored lowercase — always compare with key.toLowerCase().
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
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-
|
|
1
|
+
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';
|
|
2
2
|
import 'express';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -98,9 +98,9 @@ declare const HEADERS: {
|
|
|
98
98
|
* Must stay in sync with XSS_REMOVE_PATTERNS below.
|
|
99
99
|
*/
|
|
100
100
|
declare const XSS_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
101
|
-
declare const SQL_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
102
|
-
declare const PATH_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
103
|
-
declare const COMMAND_PATTERNS: readonly [RegExp, RegExp];
|
|
101
|
+
declare const SQL_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
102
|
+
declare const PATH_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|
|
103
|
+
declare const COMMAND_PATTERNS: readonly [RegExp, RegExp, RegExp];
|
|
104
104
|
/**
|
|
105
105
|
* Prototype pollution keys to block.
|
|
106
106
|
* Stored lowercase — always compare with key.toLowerCase().
|
package/dist/core/index.js
CHANGED
|
@@ -87,7 +87,11 @@ var SQL_PATTERNS = [
|
|
|
87
87
|
/** Time-based blind: SLEEP() */
|
|
88
88
|
/\bSLEEP\s*\(\s*\d+\s*\)/gi,
|
|
89
89
|
/** Time-based blind: BENCHMARK() */
|
|
90
|
-
/\bBENCHMARK\s*\(/gi
|
|
90
|
+
/\bBENCHMARK\s*\(/gi,
|
|
91
|
+
/** Time-based blind: PostgreSQL pg_sleep() */
|
|
92
|
+
/\bpg_sleep\s*\(/gi,
|
|
93
|
+
/** Time-based blind: MSSQL WAITFOR DELAY */
|
|
94
|
+
/\bWAITFOR\s+DELAY\b/gi
|
|
91
95
|
];
|
|
92
96
|
var PATH_PATTERNS = [
|
|
93
97
|
/** Unix path traversal */
|
|
@@ -105,6 +109,10 @@ var PATH_PATTERNS = [
|
|
|
105
109
|
/\.%2e[\\/]/gi,
|
|
106
110
|
/** Fully URL-encoded: %2e%2e%2f */
|
|
107
111
|
/%2e%2e%2f/gi,
|
|
112
|
+
/** Double URL-encoded forward slash: %252f */
|
|
113
|
+
/%252f/gi,
|
|
114
|
+
/** Dotdotslash bypass: ....// or ....\\ */
|
|
115
|
+
/\.{2,}[/\\]{2,}/g,
|
|
108
116
|
/** Null byte injection in paths */
|
|
109
117
|
/\0/g
|
|
110
118
|
];
|
|
@@ -120,7 +128,9 @@ var COMMAND_PATTERNS = [
|
|
|
120
128
|
*/
|
|
121
129
|
/[;&|`]/g,
|
|
122
130
|
/** Command substitution: $( ... ) — matched as a pair to reduce false positives */
|
|
123
|
-
/\$\(/g
|
|
131
|
+
/\$\(/g,
|
|
132
|
+
/** URL-encoded newline/carriage-return injection (%0a, %0d) */
|
|
133
|
+
/%0[ad]/gi
|
|
124
134
|
];
|
|
125
135
|
var DANGEROUS_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
126
136
|
"__proto__",
|
|
@@ -154,6 +164,7 @@ var NOSQL_DANGEROUS_KEYS = /* @__PURE__ */ new Set([
|
|
|
154
164
|
"$expr",
|
|
155
165
|
"$mod",
|
|
156
166
|
"$text",
|
|
167
|
+
"$jsonSchema",
|
|
157
168
|
// Array
|
|
158
169
|
"$elemMatch",
|
|
159
170
|
"$all",
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/constants.ts","../../src/core/errors.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * @module @arcis/node/core/constants\r\n * Named constants for Arcis - no magic numbers\r\n */\r\n\r\n// =============================================================================\r\n// INPUT LIMITS\r\n// =============================================================================\r\nexport const INPUT = {\r\n /** Default maximum input size (1MB) */\r\n DEFAULT_MAX_SIZE: 1_000_000,\r\n /** Maximum recursion depth for nested objects */\r\n MAX_RECURSION_DEPTH: 10,\r\n} as const;\r\n\r\n// =============================================================================\r\n// RATE LIMITING\r\n// =============================================================================\r\nexport const RATE_LIMIT = {\r\n /** Default window size (1 minute) */\r\n DEFAULT_WINDOW_MS: 60_000,\r\n /** Default max requests per window */\r\n DEFAULT_MAX_REQUESTS: 100,\r\n /** Default HTTP status code for rate limited responses */\r\n DEFAULT_STATUS_CODE: 429,\r\n /** Default error message */\r\n DEFAULT_MESSAGE: 'Too many requests, please try again later.',\r\n /** Minimum window size (1 second) */\r\n MIN_WINDOW_MS: 1_000,\r\n /** Maximum window size (24 hours) */\r\n MAX_WINDOW_MS: 86_400_000,\r\n} as const;\r\n\r\n// =============================================================================\r\n// SECURITY HEADERS\r\n// =============================================================================\r\nexport const HEADERS = {\r\n /** Default Content Security Policy */\r\n DEFAULT_CSP: [\r\n \"default-src 'self'\",\r\n \"script-src 'self'\",\r\n \"style-src 'self' 'unsafe-inline'\",\r\n \"img-src 'self' data: https:\",\r\n \"font-src 'self'\",\r\n \"object-src 'none'\",\r\n \"frame-ancestors 'none'\",\r\n ].join('; '),\r\n /** Default HSTS max age (1 year in seconds) */\r\n HSTS_MAX_AGE: 31_536_000,\r\n /** Default X-Frame-Options value */\r\n FRAME_OPTIONS: 'DENY' as const,\r\n /** Default X-Content-Type-Options value */\r\n CONTENT_TYPE_OPTIONS: 'nosniff',\r\n /** Default Referrer-Policy value */\r\n REFERRER_POLICY: 'strict-origin-when-cross-origin',\r\n /** Default Permissions-Policy value */\r\n PERMISSIONS_POLICY: 'geolocation=(), microphone=(), camera=()',\r\n /** Default Cache-Control value for security */\r\n CACHE_CONTROL: 'no-store, no-cache, must-revalidate, proxy-revalidate',\r\n} as const;\r\n\r\n// =============================================================================\r\n// XSS PATTERNS (ReDoS-safe)\r\n// =============================================================================\r\n\r\n/**\r\n * Detection patterns — used to flag whether a string contains XSS payloads.\r\n * Must stay in sync with XSS_REMOVE_PATTERNS below.\r\n */\r\nexport const XSS_PATTERNS = [\r\n /** Script tags (ReDoS-safe version) */\r\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\r\n /** javascript: protocol (allow optional spaces before colon) */\r\n /javascript\\s*:/gi,\r\n /** vbscript: protocol */\r\n /vbscript\\s*:/gi,\r\n /** Event handlers (onclick, onerror, etc.) — any separator before attribute */\r\n /(?:[\\s/])on\\w+\\s*=/gi,\r\n /** iframe tags */\r\n /<iframe/gi,\r\n /** object tags */\r\n /<object/gi,\r\n /** embed tags */\r\n /<embed/gi,\r\n /** data: URIs (only dangerous ones, avoid false positives) */\r\n /(?:^|[\\s\"'=])data:/gi,\r\n /** URL-encoded script tags */\r\n /%3Cscript/gi,\r\n /** SVG with onload */\r\n /<svg[^>]*onload/gi,\r\n] as const;\r\n\r\n/**\r\n * Removal patterns — used by sanitizeXss() to strip dangerous content.\r\n * More targeted than XSS_PATTERNS: each pattern captures the full dangerous\r\n * substring (tag, attribute + value, protocol) so it can be replaced safely.\r\n * Must stay in sync with XSS_PATTERNS above.\r\n */\r\nexport const XSS_REMOVE_PATTERNS = [\r\n /** Full script blocks (content + tags) */\r\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\r\n /** Standalone/unclosed script tags */\r\n /<script[^>]*>/gi,\r\n /** iframe — full block and partial/unclosed */\r\n /<iframe[^>]*>[\\s\\S]*?<\\/iframe>/gi,\r\n /<iframe[^>]*/gi,\r\n /** object — full block and partial/unclosed */\r\n /<object[^>]*>[\\s\\S]*?<\\/object>/gi,\r\n /<object[^>]*/gi,\r\n /** embed tags */\r\n /<embed[^>]*/gi,\r\n /** SVG with inline event handlers */\r\n /<svg[^>]*onload[^>]*>/gi,\r\n /** URL-encoded script tags */\r\n /%3Cscript/gi,\r\n /** Event handlers with quoted values: onclick=\"...\", onerror='...' */\r\n /(?:[\\s/])on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi,\r\n /** Event handlers with unquoted values: onload=value */\r\n /(?:[\\s/])on\\w+\\s*=\\s*[^\\s>]*/gi,\r\n /** javascript: and vbscript: protocols (allow optional spaces before colon) */\r\n /javascript\\s*:/gi,\r\n /vbscript\\s*:/gi,\r\n /** data: URIs with HTML/script content */\r\n /data\\s*:\\s*text\\/html[^>\\s]*/gi,\r\n] as const;\r\n\r\n// =============================================================================\r\n// SQL INJECTION PATTERNS\r\n// =============================================================================\r\nexport const SQL_PATTERNS = [\r\n /** SQL keywords */\r\n /(\\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER|CREATE|TRUNCATE|EXEC|EXECUTE)\\b)/gi,\r\n /** SQL comments: ANSI (--), C-style (slash-star ... star-slash), MySQL (#) */\r\n /(--|\\/\\*|\\*\\/|#)/g,\r\n /** SQL statement separators */\r\n /(;|\\|\\||&&)/g,\r\n /** Boolean injection: OR 1=1 */\r\n /\\bOR\\s+\\d+\\s*=\\s*\\d+/gi,\r\n /** Boolean injection: OR 'a'='a' or OR \"a\"=\"a\" (including mixed quotes) */\r\n /\\bOR\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\r\n /\\bOR\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\r\n /** Boolean injection: AND 1=1 */\r\n /\\bAND\\s+\\d+\\s*=\\s*\\d+/gi,\r\n /** Boolean injection: AND 'a'='a' or AND \"a\"=\"a\" (including mixed quotes) */\r\n /\\bAND\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\r\n /\\bAND\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\r\n /** Time-based blind: SLEEP() */\r\n /\\bSLEEP\\s*\\(\\s*\\d+\\s*\\)/gi,\r\n /** Time-based blind: BENCHMARK() */\r\n /\\bBENCHMARK\\s*\\(/gi,\r\n] as const;\r\n\r\n// =============================================================================\r\n// PATH TRAVERSAL PATTERNS\r\n// =============================================================================\r\nexport const PATH_PATTERNS = [\r\n /** Unix path traversal */\r\n /\\.\\.\\//g,\r\n /** Windows path traversal */\r\n /\\.\\.\\\\/g,\r\n /** URL-encoded traversal (%2e%2e) */\r\n /%2e%2e/gi,\r\n /** Double URL-encoded traversal (%252e) */\r\n /%252e/gi,\r\n /** Mixed encoding: ..%2F */\r\n /\\.\\.%2F/gi,\r\n /** Mixed encoding: %2e./ and .%2e/ */\r\n /%2e\\.[\\\\/]/gi,\r\n /\\.%2e[\\\\/]/gi,\r\n /** Fully URL-encoded: %2e%2e%2f */\r\n /%2e%2e%2f/gi,\r\n /** Null byte injection in paths */\r\n /\\0/g,\r\n] as const;\r\n\r\n// =============================================================================\r\n// COMMAND INJECTION PATTERNS\r\n// =============================================================================\r\nexport const COMMAND_PATTERNS = [\r\n /**\r\n * Shell metacharacters that enable command chaining/substitution.\r\n * Bare ( and ) are excluded — they appear in common legitimate values\r\n * (function calls in code fields, math expressions, etc.).\r\n * Command substitution is caught by the $( combined pattern below.\r\n * NOTE: ';', '&', '|' may appear in legitimate URL query strings\r\n * and Markdown; consider disabling command checking (command: false)\r\n * for fields that intentionally allow those characters.\r\n */\r\n /[;&|`]/g,\r\n /** Command substitution: $( ... ) — matched as a pair to reduce false positives */\r\n /\\$\\(/g,\r\n] as const;\r\n\r\n// =============================================================================\r\n// DANGEROUS KEYS\r\n// =============================================================================\r\n\r\n/**\r\n * Prototype pollution keys to block.\r\n * Stored lowercase — always compare with key.toLowerCase().\r\n *\r\n * Includes:\r\n * - __proto__: direct prototype assignment\r\n * - constructor: access to constructor.prototype chain\r\n * - prototype: direct prototype property\r\n * - __defineGetter__/__defineSetter__: legacy property definition (can override getters/setters)\r\n * - __lookupGetter__/__lookupSetter__: legacy property introspection\r\n */\r\nexport const DANGEROUS_PROTO_KEYS = new Set([\r\n '__proto__',\r\n 'constructor',\r\n 'prototype',\r\n '__definegetter__',\r\n '__definesetter__',\r\n '__lookupgetter__',\r\n '__lookupsetter__',\r\n]);\r\n\r\n/** MongoDB operators to block */\r\nexport const NOSQL_DANGEROUS_KEYS = new Set([\r\n // Comparison\r\n '$gt', '$gte', '$lt', '$lte', '$ne', '$eq', '$in', '$nin',\r\n // Logical\r\n '$and', '$or', '$not', '$nor',\r\n // Element / evaluation\r\n '$exists', '$type', '$regex', '$where', '$expr', '$mod', '$text',\r\n // Array\r\n '$elemMatch', '$all', '$size',\r\n // JavaScript execution (critical)\r\n '$function', '$accumulator',\r\n // Aggregation pipeline operators (injectable via $lookup etc.)\r\n '$lookup', '$match', '$project', '$group', '$sort', '$limit', '$skip',\r\n '$unwind', '$addFields', '$replaceRoot',\r\n]);\r\n\r\n// =============================================================================\r\n// REDACTION\r\n// =============================================================================\r\nexport const REDACTION = {\r\n /** Replacement text for redacted values */\r\n REPLACEMENT: '[REDACTED]',\r\n /** Truncation indicator */\r\n TRUNCATED: '[TRUNCATED]',\r\n /** Max depth indicator */\r\n MAX_DEPTH: '[MAX_DEPTH]',\r\n /** Default max message length */\r\n DEFAULT_MAX_LENGTH: 10_000,\r\n /** Default sensitive keys to redact */\r\n SENSITIVE_KEYS: new Set([\r\n 'password', 'passwd', 'pwd', 'secret', 'token', 'apikey',\r\n 'api_key', 'apiKey', 'auth', 'authorization', 'credit_card',\r\n 'creditcard', 'cc', 'ssn', 'social_security', 'private_key',\r\n 'privateKey', 'access_token', 'accessToken', 'refresh_token',\r\n 'refreshToken', 'bearer', 'jwt', 'session', 'cookie',\r\n 'credentials', 'x-api-key', 'x-auth-token',\r\n ]),\r\n} as const;\r\n\r\n// =============================================================================\r\n// VALIDATION PATTERNS\r\n// =============================================================================\r\nexport const VALIDATION = {\r\n /**\r\n * Email regex pattern.\r\n * Rejects consecutive dots in local part (e.g. test..foo@example.com),\r\n * leading/trailing dots, and other common invalid forms.\r\n */\r\n EMAIL: /^[^\\s@.][^\\s@]*(?:\\.[^\\s@.][^\\s@]*)*@[^\\s@]+\\.[^\\s@]+$/,\r\n /**\r\n * URL regex pattern.\r\n * Only allows http:// and https:// — explicitly rejects javascript:,\r\n * data:, vbscript:, and other dangerous URI schemes.\r\n */\r\n URL: /^https?:\\/\\/[^\\s/$.?#][^\\s]*$/,\r\n /** UUID regex pattern (v4) */\r\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\r\n} as const;\r\n\r\n// =============================================================================\r\n// ERROR MESSAGES\r\n// =============================================================================\r\nexport const ERRORS = {\r\n /** Generic error message (production) */\r\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\r\n /** Input too large error */\r\n INPUT_TOO_LARGE: (maxSize: number) => `Input exceeds maximum size of ${maxSize} bytes`,\r\n /** Validation error messages */\r\n VALIDATION: {\r\n REQUIRED: (field: string) => `${field} is required`,\r\n INVALID_TYPE: (field: string, type: string) => `${field} must be a ${type}`,\r\n MIN_LENGTH: (field: string, min: number) => `${field} must be at least ${min} characters`,\r\n MAX_LENGTH: (field: string, max: number) => `${field} must be at most ${max} characters`,\r\n MIN_VALUE: (field: string, min: number) => `${field} must be at least ${min}`,\r\n MAX_VALUE: (field: string, max: number) => `${field} must be at most ${max}`,\r\n INVALID_FORMAT: (field: string) => `${field} format is invalid`,\r\n INVALID_EMAIL: (field: string) => `${field} must be a valid email`,\r\n INVALID_URL: (field: string) => `${field} must be a valid URL`,\r\n INVALID_UUID: (field: string) => `${field} must be a valid UUID`,\r\n INVALID_ENUM: (field: string, values: unknown[]) => `${field} must be one of: ${values.join(', ')}`,\r\n MIN_ITEMS: (field: string, min: number) => `${field} must have at least ${min} items`,\r\n MAX_ITEMS: (field: string, max: number) => `${field} must have at most ${max} items`,\r\n },\r\n} as const;\r\n\r\n// =============================================================================\r\n// BLOCKED TEXT (for sanitizer replacements)\r\n// =============================================================================\r\nexport const BLOCKED = '[BLOCKED]' as const;\r\n","/**\r\n * @module @arcis/node/core/errors\r\n * Custom error classes for Arcis\r\n */\r\n\r\n/**\r\n * Base class for all Arcis errors\r\n */\r\nexport class ArcisError extends Error {\r\n public readonly statusCode: number;\r\n public readonly code: string;\r\n /** Whether the error message is safe to expose to API clients. */\r\n public readonly expose: boolean;\r\n\r\n constructor(message: string, statusCode = 500, code = 'ARCIS_ERROR') {\r\n super(message);\r\n this.name = 'ArcisError';\r\n this.statusCode = statusCode;\r\n this.code = code;\r\n // Client errors (4xx) have controlled messages — safe to expose.\r\n // Server errors (5xx) may contain internal details — hide by default.\r\n this.expose = statusCode < 500;\r\n\r\n // Maintains proper stack trace for where error was thrown (V8 engines)\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, this.constructor);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when input validation fails\r\n */\r\nexport class ValidationError extends ArcisError {\r\n public readonly errors: string[];\r\n\r\n constructor(errors: string[]) {\r\n super('Validation failed', 400, 'VALIDATION_ERROR');\r\n this.name = 'ValidationError';\r\n this.errors = errors;\r\n }\r\n}\r\n\r\n/** Alias for ValidationError (backwards compatibility) */\r\nexport { ValidationError as ArcisValidationError };\r\n\r\n/**\r\n * Error thrown when rate limit is exceeded\r\n */\r\nexport class RateLimitError extends ArcisError {\r\n public readonly retryAfter: number;\r\n\r\n constructor(message: string, retryAfter: number) {\r\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when input is too large\r\n */\r\nexport class InputTooLargeError extends ArcisError {\r\n public readonly maxSize: number;\r\n public readonly actualSize: number;\r\n\r\n constructor(maxSize: number, actualSize: number) {\r\n super(`Input exceeds maximum size of ${maxSize} bytes`, 413, 'INPUT_TOO_LARGE');\r\n this.name = 'InputTooLargeError';\r\n this.maxSize = maxSize;\r\n this.actualSize = actualSize;\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when security threat is detected\r\n */\r\nexport class SecurityThreatError extends ArcisError {\r\n public readonly threatType: string;\r\n public readonly pattern: string;\r\n\r\n constructor(threatType: string, pattern: string) {\r\n super('Request blocked for security reasons', 400, 'SECURITY_THREAT');\r\n this.name = 'SecurityThreatError';\r\n this.threatType = threatType;\r\n this.pattern = pattern;\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when sanitization fails\r\n */\r\nexport class SanitizationError extends ArcisError {\r\n constructor(message: string) {\r\n super(message, 400, 'SANITIZATION_ERROR');\r\n this.name = 'SanitizationError';\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/constants.ts","../../src/core/errors.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @module @arcis/node/core/constants\n * Named constants for Arcis - no magic numbers\n */\n\n// =============================================================================\n// INPUT LIMITS\n// =============================================================================\nexport const INPUT = {\n /** Default maximum input size (1MB) */\n DEFAULT_MAX_SIZE: 1_000_000,\n /** Maximum recursion depth for nested objects */\n MAX_RECURSION_DEPTH: 10,\n} as const;\n\n// =============================================================================\n// RATE LIMITING\n// =============================================================================\nexport const RATE_LIMIT = {\n /** Default window size (1 minute) */\n DEFAULT_WINDOW_MS: 60_000,\n /** Default max requests per window */\n DEFAULT_MAX_REQUESTS: 100,\n /** Default HTTP status code for rate limited responses */\n DEFAULT_STATUS_CODE: 429,\n /** Default error message */\n DEFAULT_MESSAGE: 'Too many requests, please try again later.',\n /** Minimum window size (1 second) */\n MIN_WINDOW_MS: 1_000,\n /** Maximum window size (24 hours) */\n MAX_WINDOW_MS: 86_400_000,\n} as const;\n\n// =============================================================================\n// SECURITY HEADERS\n// =============================================================================\nexport const HEADERS = {\n /** Default Content Security Policy */\n DEFAULT_CSP: [\n \"default-src 'self'\",\n \"script-src 'self'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"img-src 'self' data: https:\",\n \"font-src 'self'\",\n \"object-src 'none'\",\n \"frame-ancestors 'none'\",\n ].join('; '),\n /** Default HSTS max age (1 year in seconds) */\n HSTS_MAX_AGE: 31_536_000,\n /** Default X-Frame-Options value */\n FRAME_OPTIONS: 'DENY' as const,\n /** Default X-Content-Type-Options value */\n CONTENT_TYPE_OPTIONS: 'nosniff',\n /** Default Referrer-Policy value */\n REFERRER_POLICY: 'strict-origin-when-cross-origin',\n /** Default Permissions-Policy value */\n PERMISSIONS_POLICY: 'geolocation=(), microphone=(), camera=()',\n /** Default Cache-Control value for security */\n CACHE_CONTROL: 'no-store, no-cache, must-revalidate, proxy-revalidate',\n} as const;\n\n// =============================================================================\n// XSS PATTERNS (ReDoS-safe)\n// =============================================================================\n\n/**\n * Detection patterns — used to flag whether a string contains XSS payloads.\n * Must stay in sync with XSS_REMOVE_PATTERNS below.\n */\nexport const XSS_PATTERNS = [\n /** Script tags (ReDoS-safe version) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** javascript: protocol (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /** vbscript: protocol */\n /vbscript\\s*:/gi,\n /** Event handlers (onclick, onerror, etc.) — any separator before attribute */\n /(?:[\\s/])on\\w+\\s*=/gi,\n /** iframe tags */\n /<iframe/gi,\n /** object tags */\n /<object/gi,\n /** embed tags */\n /<embed/gi,\n /** data: URIs (only dangerous ones, avoid false positives) */\n /(?:^|[\\s\"'=])data:/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** SVG with onload */\n /<svg[^>]*onload/gi,\n] as const;\n\n/**\n * Removal patterns — used by sanitizeXss() to strip dangerous content.\n * More targeted than XSS_PATTERNS: each pattern captures the full dangerous\n * substring (tag, attribute + value, protocol) so it can be replaced safely.\n * Must stay in sync with XSS_PATTERNS above.\n */\nexport const XSS_REMOVE_PATTERNS = [\n /** Full script blocks (content + tags) */\n /<script[^>]*>[\\s\\S]*?<\\/script>/gi,\n /** Standalone/unclosed script tags */\n /<script[^>]*>/gi,\n /** iframe — full block and partial/unclosed */\n /<iframe[^>]*>[\\s\\S]*?<\\/iframe>/gi,\n /<iframe[^>]*/gi,\n /** object — full block and partial/unclosed */\n /<object[^>]*>[\\s\\S]*?<\\/object>/gi,\n /<object[^>]*/gi,\n /** embed tags */\n /<embed[^>]*/gi,\n /** SVG with inline event handlers */\n /<svg[^>]*onload[^>]*>/gi,\n /** URL-encoded script tags */\n /%3Cscript/gi,\n /** Event handlers with quoted values: onclick=\"...\", onerror='...' */\n /(?:[\\s/])on\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi,\n /** Event handlers with unquoted values: onload=value */\n /(?:[\\s/])on\\w+\\s*=\\s*[^\\s>]*/gi,\n /** javascript: and vbscript: protocols (allow optional spaces before colon) */\n /javascript\\s*:/gi,\n /vbscript\\s*:/gi,\n /** data: URIs with HTML/script content */\n /data\\s*:\\s*text\\/html[^>\\s]*/gi,\n] as const;\n\n// =============================================================================\n// SQL INJECTION PATTERNS\n// =============================================================================\nexport const SQL_PATTERNS = [\n /** SQL keywords */\n /(\\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER|CREATE|TRUNCATE|EXEC|EXECUTE)\\b)/gi,\n /** SQL comments: ANSI (--), C-style (slash-star ... star-slash), MySQL (#) */\n /(--|\\/\\*|\\*\\/|#)/g,\n /** SQL statement separators */\n /(;|\\|\\||&&)/g,\n /** Boolean injection: OR 1=1 */\n /\\bOR\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: OR 'a'='a' or OR \"a\"=\"a\" (including mixed quotes) */\n /\\bOR\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bOR\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Boolean injection: AND 1=1 */\n /\\bAND\\s+\\d+\\s*=\\s*\\d+/gi,\n /** Boolean injection: AND 'a'='a' or AND \"a\"=\"a\" (including mixed quotes) */\n /\\bAND\\s+(['\"])[^'\"]*\\1\\s*=\\s*(['\"])[^'\"]*\\2/gi,\n /\\bAND\\s+('[^']*'|\"[^\"]*\")\\s*=\\s*('[^']*'|\"[^\"]*\")/gi,\n /** Time-based blind: SLEEP() */\n /\\bSLEEP\\s*\\(\\s*\\d+\\s*\\)/gi,\n /** Time-based blind: BENCHMARK() */\n /\\bBENCHMARK\\s*\\(/gi,\n /** Time-based blind: PostgreSQL pg_sleep() */\n /\\bpg_sleep\\s*\\(/gi,\n /** Time-based blind: MSSQL WAITFOR DELAY */\n /\\bWAITFOR\\s+DELAY\\b/gi,\n] as const;\n\n// =============================================================================\n// PATH TRAVERSAL PATTERNS\n// =============================================================================\nexport const PATH_PATTERNS = [\n /** Unix path traversal */\n /\\.\\.\\//g,\n /** Windows path traversal */\n /\\.\\.\\\\/g,\n /** URL-encoded traversal (%2e%2e) */\n /%2e%2e/gi,\n /** Double URL-encoded traversal (%252e) */\n /%252e/gi,\n /** Mixed encoding: ..%2F */\n /\\.\\.%2F/gi,\n /** Mixed encoding: %2e./ and .%2e/ */\n /%2e\\.[\\\\/]/gi,\n /\\.%2e[\\\\/]/gi,\n /** Fully URL-encoded: %2e%2e%2f */\n /%2e%2e%2f/gi,\n /** Double URL-encoded forward slash: %252f */\n /%252f/gi,\n /** Dotdotslash bypass: ....// or ....\\\\ */\n /\\.{2,}[/\\\\]{2,}/g,\n /** Null byte injection in paths */\n /\\0/g,\n] as const;\n\n// =============================================================================\n// COMMAND INJECTION PATTERNS\n// =============================================================================\nexport const COMMAND_PATTERNS = [\n /**\n * Shell metacharacters that enable command chaining/substitution.\n * Bare ( and ) are excluded — they appear in common legitimate values\n * (function calls in code fields, math expressions, etc.).\n * Command substitution is caught by the $( combined pattern below.\n * NOTE: ';', '&', '|' may appear in legitimate URL query strings\n * and Markdown; consider disabling command checking (command: false)\n * for fields that intentionally allow those characters.\n */\n /[;&|`]/g,\n /** Command substitution: $( ... ) — matched as a pair to reduce false positives */\n /\\$\\(/g,\n /** URL-encoded newline/carriage-return injection (%0a, %0d) */\n /%0[ad]/gi,\n] as const;\n\n// =============================================================================\n// DANGEROUS KEYS\n// =============================================================================\n\n/**\n * Prototype pollution keys to block.\n * Stored lowercase — always compare with key.toLowerCase().\n *\n * Includes:\n * - __proto__: direct prototype assignment\n * - constructor: access to constructor.prototype chain\n * - prototype: direct prototype property\n * - __defineGetter__/__defineSetter__: legacy property definition (can override getters/setters)\n * - __lookupGetter__/__lookupSetter__: legacy property introspection\n */\nexport const DANGEROUS_PROTO_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n '__definegetter__',\n '__definesetter__',\n '__lookupgetter__',\n '__lookupsetter__',\n]);\n\n/** MongoDB operators to block */\nexport const NOSQL_DANGEROUS_KEYS = new Set([\n // Comparison\n '$gt', '$gte', '$lt', '$lte', '$ne', '$eq', '$in', '$nin',\n // Logical\n '$and', '$or', '$not', '$nor',\n // Element / evaluation\n '$exists', '$type', '$regex', '$where', '$expr', '$mod', '$text', '$jsonSchema',\n // Array\n '$elemMatch', '$all', '$size',\n // JavaScript execution (critical)\n '$function', '$accumulator',\n // Aggregation pipeline operators (injectable via $lookup etc.)\n '$lookup', '$match', '$project', '$group', '$sort', '$limit', '$skip',\n '$unwind', '$addFields', '$replaceRoot',\n]);\n\n// =============================================================================\n// REDACTION\n// =============================================================================\nexport const REDACTION = {\n /** Replacement text for redacted values */\n REPLACEMENT: '[REDACTED]',\n /** Truncation indicator */\n TRUNCATED: '[TRUNCATED]',\n /** Max depth indicator */\n MAX_DEPTH: '[MAX_DEPTH]',\n /** Default max message length */\n DEFAULT_MAX_LENGTH: 10_000,\n /** Default sensitive keys to redact */\n SENSITIVE_KEYS: new Set([\n 'password', 'passwd', 'pwd', 'secret', 'token', 'apikey',\n 'api_key', 'apiKey', 'auth', 'authorization', 'credit_card',\n 'creditcard', 'cc', 'ssn', 'social_security', 'private_key',\n 'privateKey', 'access_token', 'accessToken', 'refresh_token',\n 'refreshToken', 'bearer', 'jwt', 'session', 'cookie',\n 'credentials', 'x-api-key', 'x-auth-token',\n ]),\n} as const;\n\n// =============================================================================\n// VALIDATION PATTERNS\n// =============================================================================\nexport const VALIDATION = {\n /**\n * Email regex pattern.\n * Rejects consecutive dots in local part (e.g. test..foo@example.com),\n * leading/trailing dots, and other common invalid forms.\n */\n EMAIL: /^[^\\s@.][^\\s@]*(?:\\.[^\\s@.][^\\s@]*)*@[^\\s@]+\\.[^\\s@]+$/,\n /**\n * URL regex pattern.\n * Only allows http:// and https:// — explicitly rejects javascript:,\n * data:, vbscript:, and other dangerous URI schemes.\n */\n URL: /^https?:\\/\\/[^\\s/$.?#][^\\s]*$/,\n /** UUID regex pattern (v4) */\n UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n} as const;\n\n// =============================================================================\n// ERROR MESSAGES\n// =============================================================================\nexport const ERRORS = {\n /** Generic error message (production) */\n INTERNAL_SERVER_ERROR: 'Internal Server Error',\n /** Input too large error */\n INPUT_TOO_LARGE: (maxSize: number) => `Input exceeds maximum size of ${maxSize} bytes`,\n /** Validation error messages */\n VALIDATION: {\n REQUIRED: (field: string) => `${field} is required`,\n INVALID_TYPE: (field: string, type: string) => `${field} must be a ${type}`,\n MIN_LENGTH: (field: string, min: number) => `${field} must be at least ${min} characters`,\n MAX_LENGTH: (field: string, max: number) => `${field} must be at most ${max} characters`,\n MIN_VALUE: (field: string, min: number) => `${field} must be at least ${min}`,\n MAX_VALUE: (field: string, max: number) => `${field} must be at most ${max}`,\n INVALID_FORMAT: (field: string) => `${field} format is invalid`,\n INVALID_EMAIL: (field: string) => `${field} must be a valid email`,\n INVALID_URL: (field: string) => `${field} must be a valid URL`,\n INVALID_UUID: (field: string) => `${field} must be a valid UUID`,\n INVALID_ENUM: (field: string, values: unknown[]) => `${field} must be one of: ${values.join(', ')}`,\n MIN_ITEMS: (field: string, min: number) => `${field} must have at least ${min} items`,\n MAX_ITEMS: (field: string, max: number) => `${field} must have at most ${max} items`,\n },\n} as const;\n\n// =============================================================================\n// BLOCKED TEXT (for sanitizer replacements)\n// =============================================================================\nexport const BLOCKED = '[BLOCKED]' as const;\n","/**\n * @module @arcis/node/core/errors\n * Custom error classes for Arcis\n */\n\n/**\n * Base class for all Arcis errors\n */\nexport class ArcisError extends Error {\n public readonly statusCode: number;\n public readonly code: string;\n /** Whether the error message is safe to expose to API clients. */\n public readonly expose: boolean;\n\n constructor(message: string, statusCode = 500, code = 'ARCIS_ERROR') {\n super(message);\n this.name = 'ArcisError';\n this.statusCode = statusCode;\n this.code = code;\n // Client errors (4xx) have controlled messages — safe to expose.\n // Server errors (5xx) may contain internal details — hide by default.\n this.expose = statusCode < 500;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error thrown when input validation fails\n */\nexport class ValidationError extends ArcisError {\n public readonly errors: string[];\n\n constructor(errors: string[]) {\n super('Validation failed', 400, 'VALIDATION_ERROR');\n this.name = 'ValidationError';\n this.errors = errors;\n }\n}\n\n/** Alias for ValidationError (backwards compatibility) */\nexport { ValidationError as ArcisValidationError };\n\n/**\n * Error thrown when rate limit is exceeded\n */\nexport class RateLimitError extends ArcisError {\n public readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number) {\n super(message, 429, 'RATE_LIMIT_EXCEEDED');\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when input is too large\n */\nexport class InputTooLargeError extends ArcisError {\n public readonly maxSize: number;\n public readonly actualSize: number;\n\n constructor(maxSize: number, actualSize: number) {\n super(`Input exceeds maximum size of ${maxSize} bytes`, 413, 'INPUT_TOO_LARGE');\n this.name = 'InputTooLargeError';\n this.maxSize = maxSize;\n this.actualSize = actualSize;\n }\n}\n\n/**\n * Error thrown when security threat is detected\n */\nexport class SecurityThreatError extends ArcisError {\n public readonly threatType: string;\n public readonly pattern: string;\n\n constructor(threatType: string, pattern: string) {\n super('Request blocked for security reasons', 400, 'SECURITY_THREAT');\n this.name = 'SecurityThreatError';\n this.threatType = threatType;\n this.pattern = pattern;\n }\n}\n\n/**\n * Error thrown when sanitization fails\n */\nexport class SanitizationError extends ArcisError {\n constructor(message: string) {\n super(message, 400, 'SANITIZATION_ERROR');\n this.name = 'SanitizationError';\n }\n}\n"]}
|
package/dist/core/index.mjs
CHANGED
|
@@ -85,7 +85,11 @@ var SQL_PATTERNS = [
|
|
|
85
85
|
/** Time-based blind: SLEEP() */
|
|
86
86
|
/\bSLEEP\s*\(\s*\d+\s*\)/gi,
|
|
87
87
|
/** Time-based blind: BENCHMARK() */
|
|
88
|
-
/\bBENCHMARK\s*\(/gi
|
|
88
|
+
/\bBENCHMARK\s*\(/gi,
|
|
89
|
+
/** Time-based blind: PostgreSQL pg_sleep() */
|
|
90
|
+
/\bpg_sleep\s*\(/gi,
|
|
91
|
+
/** Time-based blind: MSSQL WAITFOR DELAY */
|
|
92
|
+
/\bWAITFOR\s+DELAY\b/gi
|
|
89
93
|
];
|
|
90
94
|
var PATH_PATTERNS = [
|
|
91
95
|
/** Unix path traversal */
|
|
@@ -103,6 +107,10 @@ var PATH_PATTERNS = [
|
|
|
103
107
|
/\.%2e[\\/]/gi,
|
|
104
108
|
/** Fully URL-encoded: %2e%2e%2f */
|
|
105
109
|
/%2e%2e%2f/gi,
|
|
110
|
+
/** Double URL-encoded forward slash: %252f */
|
|
111
|
+
/%252f/gi,
|
|
112
|
+
/** Dotdotslash bypass: ....// or ....\\ */
|
|
113
|
+
/\.{2,}[/\\]{2,}/g,
|
|
106
114
|
/** Null byte injection in paths */
|
|
107
115
|
/\0/g
|
|
108
116
|
];
|
|
@@ -118,7 +126,9 @@ var COMMAND_PATTERNS = [
|
|
|
118
126
|
*/
|
|
119
127
|
/[;&|`]/g,
|
|
120
128
|
/** Command substitution: $( ... ) — matched as a pair to reduce false positives */
|
|
121
|
-
/\$\(/g
|
|
129
|
+
/\$\(/g,
|
|
130
|
+
/** URL-encoded newline/carriage-return injection (%0a, %0d) */
|
|
131
|
+
/%0[ad]/gi
|
|
122
132
|
];
|
|
123
133
|
var DANGEROUS_PROTO_KEYS = /* @__PURE__ */ new Set([
|
|
124
134
|
"__proto__",
|
|
@@ -152,6 +162,7 @@ var NOSQL_DANGEROUS_KEYS = /* @__PURE__ */ new Set([
|
|
|
152
162
|
"$expr",
|
|
153
163
|
"$mod",
|
|
154
164
|
"$text",
|
|
165
|
+
"$jsonSchema",
|
|
155
166
|
// Array
|
|
156
167
|
"$elemMatch",
|
|
157
168
|
"$all",
|