@arcis/node 1.4.3 → 1.5.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/LICENSE +21 -0
- package/README.md +43 -5
- package/dist/astro/index.js +6141 -0
- package/dist/astro/index.js.map +1 -0
- package/dist/astro/index.mjs +6136 -0
- package/dist/astro/index.mjs.map +1 -0
- package/dist/bun/index.js +6195 -0
- package/dist/bun/index.js.map +1 -0
- package/dist/bun/index.mjs +6189 -0
- package/dist/bun/index.mjs.map +1 -0
- package/dist/core/constants.d.ts +4 -3
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/index.js +8 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +8 -4
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/types.d.ts +43 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/fastify/index.js +6160 -0
- package/dist/fastify/index.js.map +1 -0
- package/dist/fastify/index.mjs +6155 -0
- package/dist/fastify/index.mjs.map +1 -0
- package/dist/guards.d.ts +156 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/hono/index.js +6159 -0
- package/dist/hono/index.js.map +1 -0
- package/dist/hono/index.mjs +6154 -0
- package/dist/hono/index.mjs.map +1 -0
- package/dist/index.d.ts +23 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7365 -305
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7327 -306
- package/dist/index.mjs.map +1 -1
- package/dist/koa/index.js +6158 -0
- package/dist/koa/index.js.map +1 -0
- package/dist/koa/index.mjs +6153 -0
- package/dist/koa/index.mjs.map +1 -0
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/index.mjs.map +1 -1
- package/dist/logging/redactor.d.ts.map +1 -1
- package/dist/middleware/astro.d.ts +64 -0
- package/dist/middleware/astro.d.ts.map +1 -0
- package/dist/middleware/bot-detection.d.ts.map +1 -1
- package/dist/middleware/bun.d.ts +75 -0
- package/dist/middleware/bun.d.ts.map +1 -0
- package/dist/middleware/csrf.d.ts.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/fastify.d.ts +89 -0
- package/dist/middleware/fastify.d.ts.map +1 -0
- package/dist/middleware/graphql.d.ts +35 -0
- package/dist/middleware/graphql.d.ts.map +1 -0
- package/dist/middleware/hono.d.ts +63 -0
- package/dist/middleware/hono.d.ts.map +1 -0
- package/dist/middleware/index.d.ts +12 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +6693 -122
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +6683 -123
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/middleware/koa.d.ts +84 -0
- package/dist/middleware/koa.d.ts.map +1 -0
- package/dist/middleware/main.d.ts +0 -30
- package/dist/middleware/main.d.ts.map +1 -1
- package/dist/middleware/mass-assign.d.ts +81 -0
- package/dist/middleware/mass-assign.d.ts.map +1 -0
- package/dist/middleware/method-allowlist.d.ts +66 -0
- package/dist/middleware/method-allowlist.d.ts.map +1 -0
- package/dist/middleware/nestjs.d.ts +62 -0
- package/dist/middleware/nestjs.d.ts.map +1 -0
- package/dist/middleware/nextjs.d.ts +102 -0
- package/dist/middleware/nextjs.d.ts.map +1 -0
- package/dist/middleware/nuxt.d.ts +61 -0
- package/dist/middleware/nuxt.d.ts.map +1 -0
- package/dist/middleware/overload.d.ts +92 -0
- package/dist/middleware/overload.d.ts.map +1 -0
- package/dist/middleware/protect.d.ts +91 -0
- package/dist/middleware/protect.d.ts.map +1 -0
- package/dist/middleware/rate-limit-sliding.d.ts.map +1 -1
- package/dist/middleware/rate-limit-token.d.ts.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/response-splitting.d.ts +83 -0
- package/dist/middleware/response-splitting.d.ts.map +1 -0
- package/dist/middleware/sveltekit.d.ts +68 -0
- package/dist/middleware/sveltekit.d.ts.map +1 -0
- package/dist/middleware/token-budget.d.ts +75 -0
- package/dist/middleware/token-budget.d.ts.map +1 -0
- package/dist/nestjs/index.js +1724 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/nestjs/index.mjs +1717 -0
- package/dist/nestjs/index.mjs.map +1 -0
- package/dist/nextjs/index.js +6184 -0
- package/dist/nextjs/index.js.map +1 -0
- package/dist/nextjs/index.mjs +6178 -0
- package/dist/nextjs/index.mjs.map +1 -0
- package/dist/nuxt/index.js +6141 -0
- package/dist/nuxt/index.js.map +1 -0
- package/dist/nuxt/index.mjs +6136 -0
- package/dist/nuxt/index.mjs.map +1 -0
- package/dist/sanitizers/encode.d.ts.map +1 -1
- package/dist/sanitizers/graphql.d.ts +72 -0
- package/dist/sanitizers/graphql.d.ts.map +1 -0
- package/dist/sanitizers/headers.d.ts +18 -0
- package/dist/sanitizers/headers.d.ts.map +1 -1
- package/dist/sanitizers/index.d.ts +6 -2
- package/dist/sanitizers/index.d.ts.map +1 -1
- package/dist/sanitizers/index.js +339 -197
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +333 -198
- package/dist/sanitizers/index.mjs.map +1 -1
- package/dist/sanitizers/prompt-injection.d.ts +62 -0
- package/dist/sanitizers/prompt-injection.d.ts.map +1 -0
- package/dist/sanitizers/sanitize.d.ts +13 -0
- package/dist/sanitizers/sanitize.d.ts.map +1 -1
- package/dist/sanitizers/xpath.d.ts +37 -0
- package/dist/sanitizers/xpath.d.ts.map +1 -0
- package/dist/stores/index.js +4 -4
- package/dist/stores/index.js.map +1 -1
- package/dist/stores/index.mjs +4 -4
- package/dist/stores/index.mjs.map +1 -1
- package/dist/stores/redis.d.ts +7 -1
- package/dist/stores/redis.d.ts.map +1 -1
- package/dist/sveltekit/index.js +6142 -0
- package/dist/sveltekit/index.js.map +1 -0
- package/dist/sveltekit/index.mjs +6137 -0
- package/dist/sveltekit/index.mjs.map +1 -0
- package/dist/telemetry/client.d.ts +3 -0
- package/dist/telemetry/client.d.ts.map +1 -1
- package/dist/telemetry/types.d.ts +12 -0
- package/dist/telemetry/types.d.ts.map +1 -1
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +137 -12
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/index.mjs +116 -13
- package/dist/validation/index.mjs.map +1 -1
- package/dist/validation/redirect.d.ts.map +1 -1
- package/dist/validation/schema.d.ts.map +1 -1
- package/dist/validation/url-async.d.ts +137 -0
- package/dist/validation/url-async.d.ts.map +1 -0
- package/package.json +52 -4
- package/scripts/postinstall.cjs +26 -0
|
@@ -18,11 +18,14 @@ export declare class TelemetryClient {
|
|
|
18
18
|
private readonly workspaceId;
|
|
19
19
|
private readonly batchSize;
|
|
20
20
|
private readonly flushIntervalMs;
|
|
21
|
+
private readonly maxQueueSize;
|
|
21
22
|
private readonly onError;
|
|
23
|
+
private readonly onQueueOverflow;
|
|
22
24
|
private timer;
|
|
23
25
|
private flushing;
|
|
24
26
|
private closed;
|
|
25
27
|
private signalHandler;
|
|
28
|
+
private droppedSinceLastFlush;
|
|
26
29
|
constructor(options: TelemetryOptions);
|
|
27
30
|
/**
|
|
28
31
|
* Enqueue an event. Fast, synchronous, cannot throw.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/telemetry/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/telemetry/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAYhE;;;;;;;;;;;GAWG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;IACnD,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAA2B;IAIhD,OAAO,CAAC,qBAAqB,CAAK;gBAEtB,OAAO,EAAE,gBAAgB;IAkCrC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAwBnC;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B;;;;OAIG;IACH,oBAAoB,IAAI,IAAI;IAU5B,sEAAsE;IACtE,IAAI,YAAY,IAAI,MAAM,CAEzB;YAIa,IAAI;IA2BlB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;CAOnB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,MAAM,EAAE,MAAM;aACd,YAAY,EAAE,MAAM;gBADpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM;CAKvC"}
|
|
@@ -53,6 +53,18 @@ export interface TelemetryOptions {
|
|
|
53
53
|
batchSize?: number;
|
|
54
54
|
/** Periodic flush interval in milliseconds. Default: 5000. Minimum: 500. */
|
|
55
55
|
flushIntervalMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Maximum events to hold in the in-memory queue before drop-oldest kicks
|
|
58
|
+
* in. Prevents OOM during sustained dashboard outages. Default: 10_000
|
|
59
|
+
* (~10 MB at average event size). Must be >= batchSize.
|
|
60
|
+
*/
|
|
61
|
+
maxQueueSize?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Called once whenever the queue overflows and an event is dropped. Receives
|
|
64
|
+
* the count of events dropped in the current overflow window. Useful for
|
|
65
|
+
* surfacing a metric / log line so operators notice the dashboard is down.
|
|
66
|
+
*/
|
|
67
|
+
onQueueOverflow?: (droppedCount: number) => void;
|
|
56
68
|
/** Error hook for network/HTTP failures. If omitted, errors are swallowed silently. */
|
|
57
69
|
onError?: (err: Error) => void;
|
|
58
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/telemetry/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,gFAAgF;IAChF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/telemetry/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,gFAAgF;IAChF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,uFAAuF;IACvF,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC"}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
export { validate, createValidator } from './schema';
|
|
6
6
|
export { validateFile, sanitizeFilename, isDangerousExtension } from './file';
|
|
7
7
|
export { validateUrl, isUrlSafe } from './url';
|
|
8
|
+
export { validateUrlAsync, pinnedDnsLookup, safeFollowRedirect } from './url-async';
|
|
9
|
+
export type { ValidateUrlAsyncOptions, ValidateUrlAsyncResult, DnsLookup, LookupAddress, } from './url-async';
|
|
8
10
|
export { validateRedirect, isRedirectSafe } from './redirect';
|
|
9
11
|
export { validateEmail, verifyEmailMx, isValidEmailSyntax } from './email';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACpF,YAAY,EACV,uBAAuB,EACvB,sBAAsB,EACtB,SAAS,EACT,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/validation/index.js
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
var dns = require('dns');
|
|
4
4
|
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) return e;
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var dns__namespace = /*#__PURE__*/_interopNamespace(dns);
|
|
24
|
+
|
|
5
25
|
// src/core/constants.ts
|
|
6
26
|
var INPUT = {
|
|
7
27
|
/** Default maximum input size (1MB) */
|
|
@@ -33,8 +53,8 @@ var XSS_REMOVE_PATTERNS = [
|
|
|
33
53
|
/** javascript: and vbscript: protocols (allow optional spaces before colon) */
|
|
34
54
|
/javascript\s*:/gi,
|
|
35
55
|
/vbscript\s*:/gi,
|
|
36
|
-
/** data: URIs with HTML
|
|
37
|
-
/data\s*:\s*text\/html[^>\s]*/gi,
|
|
56
|
+
/** data: URIs with HTML or SVG content (SVG can run JS via inline event handlers) */
|
|
57
|
+
/data\s*:\s*(?:text\/html|image\/svg)[^>\s]*/gi,
|
|
38
58
|
/** form tag injection — phishing via action= redirection */
|
|
39
59
|
/<form[\s>][^>]*/gi,
|
|
40
60
|
/** meta tag injection — http-equiv refresh or CSP bypass */
|
|
@@ -118,10 +138,11 @@ var VALIDATION = {
|
|
|
118
138
|
EMAIL: /^[^\s@.][^\s@]*(?:\.[^\s@.][^\s@]*)*@[^\s@]+\.[^\s@]+$/,
|
|
119
139
|
/**
|
|
120
140
|
* URL regex pattern.
|
|
121
|
-
* Only allows http:// and https://
|
|
122
|
-
* data:, vbscript:, and
|
|
141
|
+
* Only allows http:// and https:// (case-insensitive scheme per
|
|
142
|
+
* RFC 3986); explicitly rejects javascript:, data:, vbscript:, and
|
|
143
|
+
* other dangerous URI schemes.
|
|
123
144
|
*/
|
|
124
|
-
URL: /^https?:\/\/[^\s/$.?#][^\s]
|
|
145
|
+
URL: /^https?:\/\/[^\s/$.?#][^\s]*$/i,
|
|
125
146
|
/** UUID regex pattern (v4) */
|
|
126
147
|
UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
127
148
|
};
|
|
@@ -402,7 +423,12 @@ function validate(schema, source = "body") {
|
|
|
402
423
|
res.status(400).json({ errors });
|
|
403
424
|
return;
|
|
404
425
|
}
|
|
405
|
-
req
|
|
426
|
+
Object.defineProperty(req, source, {
|
|
427
|
+
value: validated,
|
|
428
|
+
writable: true,
|
|
429
|
+
configurable: true,
|
|
430
|
+
enumerable: true
|
|
431
|
+
});
|
|
406
432
|
next();
|
|
407
433
|
};
|
|
408
434
|
}
|
|
@@ -899,6 +925,99 @@ function checkOctalIp(hostname, allowLocalhost, allowPrivate) {
|
|
|
899
925
|
}
|
|
900
926
|
return null;
|
|
901
927
|
}
|
|
928
|
+
var defaultLookup = (hostname) => new Promise((resolve, reject) => {
|
|
929
|
+
dns__namespace.lookup(hostname, { all: true }, (err, addresses) => {
|
|
930
|
+
if (err) reject(err);
|
|
931
|
+
else resolve(addresses);
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
function checkResolvedIp(ip, options) {
|
|
935
|
+
const isIpv6 = ip.includes(":");
|
|
936
|
+
const host = isIpv6 ? `[${ip}]` : ip;
|
|
937
|
+
const { allowedProtocols, allowLocalhost, allowPrivate } = options;
|
|
938
|
+
return validateUrl(`http://${host}/`, {
|
|
939
|
+
allowedProtocols,
|
|
940
|
+
allowLocalhost,
|
|
941
|
+
allowPrivate
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
async function validateUrlAsync(url, options = {}) {
|
|
945
|
+
const sync = validateUrl(url, options);
|
|
946
|
+
if (!sync.safe) return sync;
|
|
947
|
+
let parsed;
|
|
948
|
+
try {
|
|
949
|
+
parsed = new URL(url);
|
|
950
|
+
} catch {
|
|
951
|
+
return { safe: false, reason: "invalid URL: failed to parse" };
|
|
952
|
+
}
|
|
953
|
+
const host = parsed.hostname.replace(/^\[|\]$/g, "");
|
|
954
|
+
if (isLiteralIp(host)) return { safe: true };
|
|
955
|
+
if (options.allowedHosts?.some((h) => host.toLowerCase() === h.toLowerCase())) {
|
|
956
|
+
return { safe: true };
|
|
957
|
+
}
|
|
958
|
+
const lookup2 = options.lookup ?? defaultLookup;
|
|
959
|
+
let addresses;
|
|
960
|
+
try {
|
|
961
|
+
addresses = await lookup2(host);
|
|
962
|
+
} catch (err) {
|
|
963
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
964
|
+
return { safe: false, reason: `DNS lookup failed: ${msg}` };
|
|
965
|
+
}
|
|
966
|
+
if (addresses.length === 0) {
|
|
967
|
+
return { safe: false, reason: "DNS returned no addresses" };
|
|
968
|
+
}
|
|
969
|
+
const ips = addresses.map((a) => a.address);
|
|
970
|
+
const acceptFirstPublic = options.acceptFirstPublic === true;
|
|
971
|
+
let firstPublic;
|
|
972
|
+
for (const ip of ips) {
|
|
973
|
+
const ipResult = checkResolvedIp(ip, options);
|
|
974
|
+
if (ipResult.safe) {
|
|
975
|
+
if (firstPublic === void 0) firstPublic = ip;
|
|
976
|
+
} else if (!acceptFirstPublic) {
|
|
977
|
+
return {
|
|
978
|
+
safe: false,
|
|
979
|
+
reason: `resolved IP ${ip} is unsafe: ${ipResult.reason}`,
|
|
980
|
+
resolvedIps: ips
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
if (firstPublic === void 0) {
|
|
985
|
+
return {
|
|
986
|
+
safe: false,
|
|
987
|
+
reason: "all resolved IPs are private/loopback",
|
|
988
|
+
resolvedIps: ips
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
return { safe: true, resolvedIp: firstPublic, resolvedIps: ips };
|
|
992
|
+
}
|
|
993
|
+
function pinnedDnsLookup(ip) {
|
|
994
|
+
if (typeof ip !== "string" || ip.trim() === "") {
|
|
995
|
+
throw new TypeError("pinnedDnsLookup: ip must be a non-empty string");
|
|
996
|
+
}
|
|
997
|
+
const family = ip.includes(":") ? 6 : 4;
|
|
998
|
+
return (_hostname, _options, callback) => {
|
|
999
|
+
callback(null, ip, family);
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
async function safeFollowRedirect(prev, location, options = {}) {
|
|
1003
|
+
if (typeof location !== "string" || location.trim() === "") {
|
|
1004
|
+
return { safe: false, reason: "redirect Location is empty" };
|
|
1005
|
+
}
|
|
1006
|
+
let absolute;
|
|
1007
|
+
try {
|
|
1008
|
+
absolute = new URL(location, prev);
|
|
1009
|
+
} catch {
|
|
1010
|
+
return { safe: false, reason: "invalid redirect URL" };
|
|
1011
|
+
}
|
|
1012
|
+
return validateUrlAsync(absolute.toString(), options);
|
|
1013
|
+
}
|
|
1014
|
+
function isLiteralIp(host) {
|
|
1015
|
+
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host)) return true;
|
|
1016
|
+
if (/^\d+$/.test(host)) return true;
|
|
1017
|
+
if (/^0[0-7x]/.test(host) && /^[0-9a-fx.]+$/i.test(host) && host.includes(".")) return true;
|
|
1018
|
+
if (host.includes(":") && !/[/\s]/.test(host)) return true;
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
902
1021
|
|
|
903
1022
|
// src/validation/redirect.ts
|
|
904
1023
|
var DANGEROUS_PROTOCOLS = /^(javascript|data|vbscript|blob):/i;
|
|
@@ -913,8 +1032,8 @@ function validateRedirect(url, options = {}) {
|
|
|
913
1032
|
return { safe: false, reason: "invalid redirect: empty or not a string" };
|
|
914
1033
|
}
|
|
915
1034
|
const cleaned = url.replace(CONTROL_CHARS, "");
|
|
916
|
-
|
|
917
|
-
|
|
1035
|
+
const proto = cleaned.match(DANGEROUS_PROTOCOLS);
|
|
1036
|
+
if (proto) {
|
|
918
1037
|
return { safe: false, reason: `dangerous protocol: ${proto[0]}` };
|
|
919
1038
|
}
|
|
920
1039
|
if (cleaned.startsWith("\\")) {
|
|
@@ -944,11 +1063,12 @@ function validateRedirect(url, options = {}) {
|
|
|
944
1063
|
return { safe: false, reason: `disallowed protocol: ${parsed.protocol}` };
|
|
945
1064
|
}
|
|
946
1065
|
const hostname = parsed.hostname.toLowerCase();
|
|
1066
|
+
const hostWithPort = parsed.port ? `${hostname}:${parsed.port}` : hostname;
|
|
947
1067
|
if (allowedHosts.length === 0) {
|
|
948
1068
|
return { safe: false, reason: "absolute URL not in allowed hosts" };
|
|
949
1069
|
}
|
|
950
|
-
if (!allowedHosts.some((h) =>
|
|
951
|
-
return { safe: false, reason: `host not allowed: ${
|
|
1070
|
+
if (!allowedHosts.some((h) => h.toLowerCase() === hostWithPort)) {
|
|
1071
|
+
return { safe: false, reason: `host not allowed: ${hostWithPort}` };
|
|
952
1072
|
}
|
|
953
1073
|
return { safe: true };
|
|
954
1074
|
}
|
|
@@ -956,8 +1076,10 @@ function isRedirectSafe(url, options = {}) {
|
|
|
956
1076
|
return validateRedirect(url, options).safe;
|
|
957
1077
|
}
|
|
958
1078
|
function extractHost(url) {
|
|
959
|
-
const match = url.match(/^\/\/([
|
|
960
|
-
|
|
1079
|
+
const match = url.match(/^\/\/([^/?#]+)/);
|
|
1080
|
+
if (!match) return null;
|
|
1081
|
+
const authority = match[1].includes("@") ? match[1].slice(match[1].indexOf("@") + 1) : match[1];
|
|
1082
|
+
return authority.toLowerCase();
|
|
961
1083
|
}
|
|
962
1084
|
var MAX_EMAIL_LENGTH = 254;
|
|
963
1085
|
var MAX_LOCAL_LENGTH = 64;
|
|
@@ -1216,12 +1338,15 @@ exports.isDangerousExtension = isDangerousExtension;
|
|
|
1216
1338
|
exports.isRedirectSafe = isRedirectSafe;
|
|
1217
1339
|
exports.isUrlSafe = isUrlSafe;
|
|
1218
1340
|
exports.isValidEmailSyntax = isValidEmailSyntax;
|
|
1341
|
+
exports.pinnedDnsLookup = pinnedDnsLookup;
|
|
1342
|
+
exports.safeFollowRedirect = safeFollowRedirect;
|
|
1219
1343
|
exports.sanitizeFilename = sanitizeFilename;
|
|
1220
1344
|
exports.validate = validate;
|
|
1221
1345
|
exports.validateEmail = validateEmail;
|
|
1222
1346
|
exports.validateFile = validateFile;
|
|
1223
1347
|
exports.validateRedirect = validateRedirect;
|
|
1224
1348
|
exports.validateUrl = validateUrl;
|
|
1349
|
+
exports.validateUrlAsync = validateUrlAsync;
|
|
1225
1350
|
exports.verifyEmailMx = verifyEmailMx;
|
|
1226
1351
|
//# sourceMappingURL=index.js.map
|
|
1227
1352
|
//# sourceMappingURL=index.js.map
|