@arcis/node 1.4.4 → 1.5.1
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 +36 -6
- 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 +3 -2
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/index.js +4 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +4 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/types.d.ts +32 -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 +7126 -178
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7088 -179
- 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 +6469 -119
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +6459 -120
- 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 +4 -1
- package/dist/sanitizers/index.d.ts.map +1 -1
- package/dist/sanitizers/index.js +140 -66
- package/dist/sanitizers/index.js.map +1 -1
- package/dist/sanitizers/index.mjs +135 -67
- 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 +1 -1
- 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/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 +57 -12
- package/scripts/postinstall.cjs +26 -0
- package/dist/cli/arcis.d.ts +0 -23
- package/dist/cli/arcis.d.ts.map +0 -1
- package/dist/cli/arcis.js +0 -312
- package/dist/cli/arcis.js.map +0 -1
- package/dist/cli/arcis.mjs +0 -309
- package/dist/cli/arcis.mjs.map +0 -1
|
@@ -1 +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,
|
|
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,CA2ExB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAE1F"}
|
|
@@ -1 +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,
|
|
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,CAkChB;AAoKD;;;GAGG;AACH,eAAO,MAAM,eAAe,iBAAW,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @arcis/node/validation/url-async
|
|
3
|
+
*
|
|
4
|
+
* Async SSRF guard that closes the DNS-rebinding TOCTOU gap left open
|
|
5
|
+
* by the synchronous `validateUrl` (sdk-vectors.md #31, issue #50).
|
|
6
|
+
*
|
|
7
|
+
* The synchronous `validateUrl` only checks the *string form* of the
|
|
8
|
+
* hostname. It catches obvious cases — `127.0.0.1`, `10.0.0.1`,
|
|
9
|
+
* `169.254.169.254` — but a hostname like `evil.com` passes through
|
|
10
|
+
* even when its DNS A-record points to `10.0.0.1`, because resolution
|
|
11
|
+
* happens later inside `fetch`. An attacker controlling the
|
|
12
|
+
* `evil.com` zone can also rebind the answer between Arcis's check
|
|
13
|
+
* and the actual TCP connect, which is the classic DNS TOCTOU.
|
|
14
|
+
*
|
|
15
|
+
* Two layers of fix shipped here:
|
|
16
|
+
*
|
|
17
|
+
* 1. **`validateUrlAsync(url, options)`** — runs the existing sync
|
|
18
|
+
* `validateUrl` first, then `dns.lookup(hostname, { all: true })`,
|
|
19
|
+
* then re-runs the same private-range check on every resolved
|
|
20
|
+
* address. Returns the pinned IP list so callers can reuse it for
|
|
21
|
+
* the actual connection (closing the TOCTOU window).
|
|
22
|
+
*
|
|
23
|
+
* 2. **`pinnedDnsLookup(ip)`** — returns a Node `lookup` callback
|
|
24
|
+
* that resolves any hostname to the pre-validated IP. Wire this
|
|
25
|
+
* into `https.request({ lookup })` / `http.request({ lookup })`
|
|
26
|
+
* so the connection uses the IP Arcis already validated, not
|
|
27
|
+
* whatever DNS returns at connect time. Pure stdlib — no undici,
|
|
28
|
+
* no extra dep.
|
|
29
|
+
*
|
|
30
|
+
* 3. **`safeFollowRedirect(prev, location, options)`** — when the
|
|
31
|
+
* server replies 30x, run the same async guard against the new
|
|
32
|
+
* Location URL. Resolves the absolute URL using the previous
|
|
33
|
+
* response URL as base. Caller decides whether to follow.
|
|
34
|
+
*
|
|
35
|
+
* The function signatures keep `lookup` injectable so tests can
|
|
36
|
+
* substitute a fake resolver without monkey-patching `node:dns`.
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* import https from 'node:https';
|
|
40
|
+
* import { validateUrlAsync, pinnedDnsLookup } from '@arcis/node';
|
|
41
|
+
*
|
|
42
|
+
* const result = await validateUrlAsync(url);
|
|
43
|
+
* if (!result.safe) throw new Error(result.reason);
|
|
44
|
+
*
|
|
45
|
+
* https.get(url, { lookup: pinnedDnsLookup(result.resolvedIp!) }, (res) => {
|
|
46
|
+
* // The TCP connect now goes to result.resolvedIp regardless of
|
|
47
|
+
* // what DNS would say at this exact moment.
|
|
48
|
+
* });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
import { type ValidateUrlOptions, type ValidateUrlResult } from './url';
|
|
52
|
+
/**
|
|
53
|
+
* Subset of `dns.lookup`'s `{ all: true }` callback signature. Kept
|
|
54
|
+
* narrow so a test fake can satisfy it without depending on Node's
|
|
55
|
+
* full `LookupAddress` type.
|
|
56
|
+
*/
|
|
57
|
+
export type LookupAddress = {
|
|
58
|
+
address: string;
|
|
59
|
+
family: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Function shape compatible with `dns.lookup(hostname, { all: true })`.
|
|
63
|
+
* Returns a list of resolved addresses. Tests inject a fake.
|
|
64
|
+
*/
|
|
65
|
+
export type DnsLookup = (hostname: string) => Promise<LookupAddress[]>;
|
|
66
|
+
export interface ValidateUrlAsyncOptions extends ValidateUrlOptions {
|
|
67
|
+
/**
|
|
68
|
+
* DNS lookup function. Defaults to a Promise wrapper around
|
|
69
|
+
* `dns.lookup(hostname, { all: true })`. Tests inject a stub.
|
|
70
|
+
*/
|
|
71
|
+
lookup?: DnsLookup;
|
|
72
|
+
/**
|
|
73
|
+
* If true, accept the first non-private IP and ignore the rest.
|
|
74
|
+
* Default false: every resolved IP must pass the private-range
|
|
75
|
+
* check. Hosts with mixed-public/private answers (round-robin DNS
|
|
76
|
+
* with one internal record) still fail-closed.
|
|
77
|
+
*/
|
|
78
|
+
acceptFirstPublic?: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface ValidateUrlAsyncResult extends ValidateUrlResult {
|
|
81
|
+
/**
|
|
82
|
+
* Single pinned IP (the first public address if all checks passed,
|
|
83
|
+
* or undefined when the string-only synchronous validator already
|
|
84
|
+
* decided — e.g., the hostname *was* a literal IP). Use this with
|
|
85
|
+
* `pinnedDnsLookup()` to wire the actual fetch.
|
|
86
|
+
*/
|
|
87
|
+
resolvedIp?: string;
|
|
88
|
+
/** Every IP returned by DNS, in resolver order. */
|
|
89
|
+
resolvedIps?: string[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Async SSRF guard with DNS resolution. Runs the sync validator
|
|
93
|
+
* first, then resolves DNS and validates every returned IP against
|
|
94
|
+
* the same private-range rules. Returns a pinned IP for the caller
|
|
95
|
+
* to reuse.
|
|
96
|
+
*
|
|
97
|
+
* Failure modes (any returns `{ safe: false, reason }`):
|
|
98
|
+
* - Sync validator already rejects (string-pattern fail).
|
|
99
|
+
* - DNS lookup throws (NXDOMAIN, network error). Reason carries the
|
|
100
|
+
* underlying error message.
|
|
101
|
+
* - DNS returns no addresses.
|
|
102
|
+
* - Any resolved address fails the private-range check (default) or
|
|
103
|
+
* *all* fail it when `acceptFirstPublic` is true.
|
|
104
|
+
*/
|
|
105
|
+
export declare function validateUrlAsync(url: string, options?: ValidateUrlAsyncOptions): Promise<ValidateUrlAsyncResult>;
|
|
106
|
+
/**
|
|
107
|
+
* Build a `lookup` callback that pins the resolution to a single
|
|
108
|
+
* pre-validated IP, regardless of what DNS would say at connect time.
|
|
109
|
+
* Drop into `https.request({ lookup })` / `http.request({ lookup })`.
|
|
110
|
+
*
|
|
111
|
+
* Closes the TOCTOU window between `validateUrlAsync` and the actual
|
|
112
|
+
* TCP connect. The pinned IP must be one that already passed the
|
|
113
|
+
* async validator — wiring it without that check defeats the purpose.
|
|
114
|
+
*
|
|
115
|
+
* The returned function matches Node's `dns.lookup` callback shape
|
|
116
|
+
* for the `{ all: false, family: 0 }` case (single address). The
|
|
117
|
+
* default Node http/https stack uses that shape.
|
|
118
|
+
*/
|
|
119
|
+
export declare function pinnedDnsLookup(ip: string): (hostname: string, options: {
|
|
120
|
+
family?: number;
|
|
121
|
+
hints?: number;
|
|
122
|
+
verbatim?: boolean;
|
|
123
|
+
}, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void) => void;
|
|
124
|
+
/**
|
|
125
|
+
* Validate a redirect target with the same TOCTOU-aware pipeline.
|
|
126
|
+
*
|
|
127
|
+
* `prev` is the URL of the response that returned the 30x; `location`
|
|
128
|
+
* is the raw `Location:` header value (which may be relative). The
|
|
129
|
+
* function resolves `location` against `prev` per RFC 3986 then runs
|
|
130
|
+
* `validateUrlAsync` on the absolute result.
|
|
131
|
+
*
|
|
132
|
+
* Use this on every hop of a redirect chain. Without it, a server
|
|
133
|
+
* that you trust today can redirect tomorrow's request to
|
|
134
|
+
* `http://169.254.169.254/`.
|
|
135
|
+
*/
|
|
136
|
+
export declare function safeFollowRedirect(prev: string, location: string, options?: ValidateUrlAsyncOptions): Promise<ValidateUrlAsyncResult>;
|
|
137
|
+
//# sourceMappingURL=url-async.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-async.d.ts","sourceRoot":"","sources":["../../src/validation/url-async.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAGH,OAAO,EAAe,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAErF;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;AAUvE,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA0BD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CA4DjC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,GACT,CACD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,EAChE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,KACnF,IAAI,CAQR;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,sBAAsB,CAAC,CAWjC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcis/node",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Inside-the-app security middleware for Node.js. One install protects Express, NestJS, SvelteKit, Astro, Nuxt, Bun + Hono against XSS, SQL injection, CSRF, SSRF, HPP, prompt injection, bot traffic, rate limiting, and 20+ more attack types. Includes prompt-injection signature library, LLM token-budget middleware, 646-pattern bot corpus, and the @arcis/cli supply-chain scanner.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -50,14 +50,57 @@
|
|
|
50
50
|
"types": "./dist/telemetry/index.d.ts",
|
|
51
51
|
"import": "./dist/telemetry/index.mjs",
|
|
52
52
|
"require": "./dist/telemetry/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./fastify": {
|
|
55
|
+
"types": "./dist/fastify/index.d.ts",
|
|
56
|
+
"import": "./dist/fastify/index.mjs",
|
|
57
|
+
"require": "./dist/fastify/index.js"
|
|
58
|
+
},
|
|
59
|
+
"./koa": {
|
|
60
|
+
"types": "./dist/koa/index.d.ts",
|
|
61
|
+
"import": "./dist/koa/index.mjs",
|
|
62
|
+
"require": "./dist/koa/index.js"
|
|
63
|
+
},
|
|
64
|
+
"./nestjs": {
|
|
65
|
+
"types": "./dist/nestjs/index.d.ts",
|
|
66
|
+
"import": "./dist/nestjs/index.mjs",
|
|
67
|
+
"require": "./dist/nestjs/index.js"
|
|
68
|
+
},
|
|
69
|
+
"./nextjs": {
|
|
70
|
+
"types": "./dist/nextjs/index.d.ts",
|
|
71
|
+
"import": "./dist/nextjs/index.mjs",
|
|
72
|
+
"require": "./dist/nextjs/index.js"
|
|
73
|
+
},
|
|
74
|
+
"./sveltekit": {
|
|
75
|
+
"types": "./dist/sveltekit/index.d.ts",
|
|
76
|
+
"import": "./dist/sveltekit/index.mjs",
|
|
77
|
+
"require": "./dist/sveltekit/index.js"
|
|
78
|
+
},
|
|
79
|
+
"./astro": {
|
|
80
|
+
"types": "./dist/astro/index.d.ts",
|
|
81
|
+
"import": "./dist/astro/index.mjs",
|
|
82
|
+
"require": "./dist/astro/index.js"
|
|
83
|
+
},
|
|
84
|
+
"./nuxt": {
|
|
85
|
+
"types": "./dist/nuxt/index.d.ts",
|
|
86
|
+
"import": "./dist/nuxt/index.mjs",
|
|
87
|
+
"require": "./dist/nuxt/index.js"
|
|
88
|
+
},
|
|
89
|
+
"./bun": {
|
|
90
|
+
"types": "./dist/bun/index.d.ts",
|
|
91
|
+
"import": "./dist/bun/index.mjs",
|
|
92
|
+
"require": "./dist/bun/index.js"
|
|
93
|
+
},
|
|
94
|
+
"./hono": {
|
|
95
|
+
"types": "./dist/hono/index.d.ts",
|
|
96
|
+
"import": "./dist/hono/index.mjs",
|
|
97
|
+
"require": "./dist/hono/index.js"
|
|
53
98
|
}
|
|
54
99
|
},
|
|
55
100
|
"files": [
|
|
56
|
-
"dist"
|
|
101
|
+
"dist",
|
|
102
|
+
"scripts/postinstall.cjs"
|
|
57
103
|
],
|
|
58
|
-
"bin": {
|
|
59
|
-
"arcis": "./dist/cli/arcis.mjs"
|
|
60
|
-
},
|
|
61
104
|
"scripts": {
|
|
62
105
|
"build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap",
|
|
63
106
|
"dev": "tsup --watch",
|
|
@@ -68,7 +111,8 @@
|
|
|
68
111
|
"test:coverage": "vitest --coverage",
|
|
69
112
|
"lint": "eslint src",
|
|
70
113
|
"typecheck": "tsc --noEmit",
|
|
71
|
-
"prepublishOnly": "npm run build"
|
|
114
|
+
"prepublishOnly": "npm run build",
|
|
115
|
+
"postinstall": "node scripts/postinstall.cjs"
|
|
72
116
|
},
|
|
73
117
|
"keywords": [
|
|
74
118
|
"security",
|
|
@@ -100,15 +144,16 @@
|
|
|
100
144
|
"express": ">=4.0.0"
|
|
101
145
|
},
|
|
102
146
|
"devDependencies": {
|
|
147
|
+
"@nestjs/common": "^11.1.21",
|
|
103
148
|
"@types/express": "^5.0.6",
|
|
104
|
-
"@types/node": "^25.
|
|
105
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
149
|
+
"@types/node": "^25.9.1",
|
|
150
|
+
"@typescript-eslint/eslint-plugin": "^8.59.4",
|
|
106
151
|
"@typescript-eslint/parser": "^8.58.0",
|
|
107
|
-
"@vitest/coverage-v8": "^4.1.
|
|
108
|
-
"eslint": "^10.
|
|
152
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
153
|
+
"eslint": "^10.4.0",
|
|
109
154
|
"express": "^5.2.1",
|
|
110
155
|
"tsup": "^8.0.1",
|
|
111
|
-
"typescript": "^6.0.
|
|
156
|
+
"typescript": "^6.0.3",
|
|
112
157
|
"vitest": "^4.1.0"
|
|
113
158
|
},
|
|
114
159
|
"repository": {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Postinstall notice for @arcis/node.
|
|
3
|
+
//
|
|
4
|
+
// Surface the fact that the Arcis CLI (audit / scan / sca) ships as a
|
|
5
|
+
// separate native binary. Without this message, users who installed the
|
|
6
|
+
// Node SDK type `arcis` in their shell, get "command not found", and
|
|
7
|
+
// assume the package is broken.
|
|
8
|
+
//
|
|
9
|
+
// Skip in CI / non-TTY / when npm asks us not to log.
|
|
10
|
+
if (process.env.CI || process.env.ARCIS_SKIP_NOTICE) return;
|
|
11
|
+
|
|
12
|
+
const isTTY = process.stdout && process.stdout.isTTY;
|
|
13
|
+
const c = (s, code) => (isTTY ? `\x1b[${code}m${s}\x1b[0m` : s);
|
|
14
|
+
|
|
15
|
+
const lines = [
|
|
16
|
+
'',
|
|
17
|
+
c(' Arcis Node SDK installed.', '1;36'),
|
|
18
|
+
'',
|
|
19
|
+
c(' The CLI (audit / scan / sca) ships separately as a native binary:', '2'),
|
|
20
|
+
c(' npm install -g @arcis/cli', '32'),
|
|
21
|
+
'',
|
|
22
|
+
c(' This package is the SDK / middleware. It does not put a CLI on', '2'),
|
|
23
|
+
c(' your shell PATH. Docs: https://gagancm.github.io/arcis/documentation/cli.html', '2'),
|
|
24
|
+
'',
|
|
25
|
+
];
|
|
26
|
+
for (const line of lines) console.log(line);
|
package/dist/cli/arcis.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* @arcis/node — `arcis` CLI dispatcher.
|
|
4
|
-
*
|
|
5
|
-
* Surface (mirrors the Python CLI's discovery layer):
|
|
6
|
-
*
|
|
7
|
-
* arcis → catalog
|
|
8
|
-
* arcis --list → catalog with examples
|
|
9
|
-
* arcis --help / -h → catalog + run-cmd hint
|
|
10
|
-
* arcis --version / -V
|
|
11
|
-
* arcis update [--apply] [--check]
|
|
12
|
-
* arcis scan / audit / sca → forward to Python `arcis` if on PATH,
|
|
13
|
-
* else print install hint
|
|
14
|
-
*
|
|
15
|
-
* Why we delegate scan/audit/sca to Python rather than re-implementing:
|
|
16
|
-
* the threat database, audit rules, and attack-payload catalog are
|
|
17
|
-
* Python-side data files. Maintaining two copies means drift; one
|
|
18
|
-
* canonical CLI + a thin Node forwarder is simpler. The Node binary
|
|
19
|
-
* exists primarily so users who installed `@arcis/node` from npm get
|
|
20
|
-
* the same `arcis update` / discovery UX as Python users.
|
|
21
|
-
*/
|
|
22
|
-
export {};
|
|
23
|
-
//# sourceMappingURL=arcis.d.ts.map
|
package/dist/cli/arcis.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"arcis.d.ts","sourceRoot":"","sources":["../../src/cli/arcis.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
package/dist/cli/arcis.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var child_process = require('child_process');
|
|
5
|
-
var fs = require('fs');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var url = require('url');
|
|
8
|
-
|
|
9
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
10
|
-
var USE_COLOR = !process.env.NO_COLOR && process.stdout.isTTY === true;
|
|
11
|
-
function c(text, ...codes) {
|
|
12
|
-
if (!USE_COLOR) return text;
|
|
13
|
-
return codes.join("") + text + "\x1B[0m";
|
|
14
|
-
}
|
|
15
|
-
var BOLD = "\x1B[1m";
|
|
16
|
-
var DIM = "\x1B[2m";
|
|
17
|
-
var GREEN = "\x1B[32m";
|
|
18
|
-
var YELLOW = "\x1B[33m";
|
|
19
|
-
var CYAN = "\x1B[36m";
|
|
20
|
-
var RED = "\x1B[31m";
|
|
21
|
-
function getInstalledVersion() {
|
|
22
|
-
try {
|
|
23
|
-
const here = url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('arcis.js', document.baseURI).href)));
|
|
24
|
-
let dir = path.dirname(here);
|
|
25
|
-
for (let i = 0; i < 6; i++) {
|
|
26
|
-
try {
|
|
27
|
-
const raw = fs.readFileSync(path.resolve(dir, "package.json"), "utf-8");
|
|
28
|
-
const pkg = JSON.parse(raw);
|
|
29
|
-
if (pkg.name === "@arcis/node" && pkg.version) {
|
|
30
|
-
return pkg.version;
|
|
31
|
-
}
|
|
32
|
-
} catch {
|
|
33
|
-
}
|
|
34
|
-
const parent = path.resolve(dir, "..");
|
|
35
|
-
if (parent === dir) break;
|
|
36
|
-
dir = parent;
|
|
37
|
-
}
|
|
38
|
-
} catch {
|
|
39
|
-
}
|
|
40
|
-
return "?";
|
|
41
|
-
}
|
|
42
|
-
async function fetchLatestVersion() {
|
|
43
|
-
try {
|
|
44
|
-
const controller = new AbortController();
|
|
45
|
-
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
46
|
-
try {
|
|
47
|
-
const resp = await fetch("https://registry.npmjs.org/@arcis/node", {
|
|
48
|
-
headers: { Accept: "application/json" },
|
|
49
|
-
signal: controller.signal
|
|
50
|
-
});
|
|
51
|
-
if (!resp.ok) return null;
|
|
52
|
-
const data = await resp.json();
|
|
53
|
-
return data["dist-tags"]?.latest ?? null;
|
|
54
|
-
} finally {
|
|
55
|
-
clearTimeout(timer);
|
|
56
|
-
}
|
|
57
|
-
} catch {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function parseVersion(v) {
|
|
62
|
-
const parts = v.split(".");
|
|
63
|
-
const out = [];
|
|
64
|
-
for (const p of parts) {
|
|
65
|
-
if (!/^\d+$/.test(p)) return null;
|
|
66
|
-
out.push(Number(p));
|
|
67
|
-
}
|
|
68
|
-
return out;
|
|
69
|
-
}
|
|
70
|
-
function versionCompare(a, b) {
|
|
71
|
-
const len = Math.max(a.length, b.length);
|
|
72
|
-
for (let i = 0; i < len; i++) {
|
|
73
|
-
const x = a[i] ?? 0;
|
|
74
|
-
const y = b[i] ?? 0;
|
|
75
|
-
if (x < y) return -1;
|
|
76
|
-
if (x > y) return 1;
|
|
77
|
-
}
|
|
78
|
-
return 0;
|
|
79
|
-
}
|
|
80
|
-
function hasPythonArcis() {
|
|
81
|
-
const probes = [
|
|
82
|
-
{ cmd: "arcis", args: ["--version"] },
|
|
83
|
-
{ cmd: "python", args: ["-m", "arcis.cli", "--version"] },
|
|
84
|
-
{ cmd: "python3", args: ["-m", "arcis.cli", "--version"] }
|
|
85
|
-
];
|
|
86
|
-
for (const p of probes) {
|
|
87
|
-
try {
|
|
88
|
-
const result = child_process.spawnSync(p.cmd, p.args, {
|
|
89
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
90
|
-
timeout: 3e3,
|
|
91
|
-
shell: process.platform === "win32"
|
|
92
|
-
});
|
|
93
|
-
if (result.status === 0) return true;
|
|
94
|
-
} catch {
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
function forwardToPython(args) {
|
|
100
|
-
const candidates = [
|
|
101
|
-
{ cmd: "arcis", args },
|
|
102
|
-
{ cmd: "python", args: ["-m", "arcis.cli", ...args] },
|
|
103
|
-
{ cmd: "python3", args: ["-m", "arcis.cli", ...args] }
|
|
104
|
-
];
|
|
105
|
-
for (const cand of candidates) {
|
|
106
|
-
const result = child_process.spawnSync(cand.cmd, cand.args, {
|
|
107
|
-
stdio: "inherit",
|
|
108
|
-
shell: process.platform === "win32"
|
|
109
|
-
});
|
|
110
|
-
if (result.error) continue;
|
|
111
|
-
process.exit(result.status ?? 0);
|
|
112
|
-
}
|
|
113
|
-
console.error(
|
|
114
|
-
c("arcis: could not invoke the Python CLI. Install with:", RED, BOLD)
|
|
115
|
-
);
|
|
116
|
-
console.error(" pip install arcis");
|
|
117
|
-
process.exit(127);
|
|
118
|
-
}
|
|
119
|
-
function printCatalog(verbose) {
|
|
120
|
-
const ver = getInstalledVersion();
|
|
121
|
-
console.log();
|
|
122
|
-
console.log(` ${c("Arcis", BOLD, CYAN)} ${c(`v${ver}`, DIM)} ${c("(node)", DIM)}`);
|
|
123
|
-
console.log(c(" Zero-dep security middleware + scanners.", DIM));
|
|
124
|
-
console.log();
|
|
125
|
-
console.log(c(" Commands", BOLD));
|
|
126
|
-
const rows = [
|
|
127
|
-
[
|
|
128
|
-
"scan",
|
|
129
|
-
"Send live attack payloads to a running app.",
|
|
130
|
-
"arcis scan http://localhost:8000 --route POST:/echo --field q"
|
|
131
|
-
],
|
|
132
|
-
[
|
|
133
|
-
"audit",
|
|
134
|
-
"Static-analyse Python / JS / TS source for unsafe patterns.",
|
|
135
|
-
"arcis audit ."
|
|
136
|
-
],
|
|
137
|
-
[
|
|
138
|
-
"sca",
|
|
139
|
-
"Match installed dependencies against the supply-chain threat DB.",
|
|
140
|
-
"arcis sca ."
|
|
141
|
-
],
|
|
142
|
-
["update", "Check npm for a newer @arcis/node release.", "arcis update --apply"]
|
|
143
|
-
];
|
|
144
|
-
for (const [name, desc, example] of rows) {
|
|
145
|
-
console.log(` ${c(name.padEnd(8), BOLD, GREEN)} ${desc}`);
|
|
146
|
-
if (verbose) {
|
|
147
|
-
console.log(` ${c(example, DIM)}`);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
console.log();
|
|
151
|
-
console.log(c(" Discovery", BOLD));
|
|
152
|
-
console.log(` ${c("--list", BOLD, CYAN).padEnd(24)} Show this catalog (verbose).`);
|
|
153
|
-
console.log(
|
|
154
|
-
` ${c("<cmd> --help", BOLD, CYAN).padEnd(24)} Show full flags for that command.`
|
|
155
|
-
);
|
|
156
|
-
console.log();
|
|
157
|
-
console.log(c(" Note", BOLD));
|
|
158
|
-
console.log(
|
|
159
|
-
` scan/audit/sca delegate to the Python CLI (canonical impl).`
|
|
160
|
-
);
|
|
161
|
-
console.log(` Install once with: ${c("pip install arcis", GREEN)}`);
|
|
162
|
-
console.log();
|
|
163
|
-
}
|
|
164
|
-
async function updateCommand(args) {
|
|
165
|
-
const apply = args.includes("--apply");
|
|
166
|
-
const check = args.includes("--check");
|
|
167
|
-
const yes = args.includes("--yes") || args.includes("-y");
|
|
168
|
-
const current = getInstalledVersion();
|
|
169
|
-
const latest = await fetchLatestVersion();
|
|
170
|
-
if (check) {
|
|
171
|
-
if (latest === null) {
|
|
172
|
-
console.error("arcis: could not reach npm to check for updates");
|
|
173
|
-
process.exitCode = 2;
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
const cur2 = parseVersion(current);
|
|
177
|
-
const lat2 = parseVersion(latest);
|
|
178
|
-
if (!cur2 || !lat2 || versionCompare(cur2, lat2) >= 0) {
|
|
179
|
-
console.log(`@arcis/node ${current} is up-to-date`);
|
|
180
|
-
process.exitCode = 0;
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
console.error(`@arcis/node ${current} is outdated; latest is ${latest}`);
|
|
184
|
-
process.exitCode = 1;
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
console.log();
|
|
188
|
-
console.log(c(" @arcis/node update check", BOLD, CYAN));
|
|
189
|
-
console.log(c(" Source: https://registry.npmjs.org/@arcis/node", DIM));
|
|
190
|
-
console.log();
|
|
191
|
-
if (latest === null) {
|
|
192
|
-
console.log(` Installed @arcis/node ${current}`);
|
|
193
|
-
console.log(
|
|
194
|
-
` Latest ${c("? unreachable", YELLOW)} ${c("(network error or npm down)", DIM)}`
|
|
195
|
-
);
|
|
196
|
-
console.log();
|
|
197
|
-
console.log(c(" Try again later, or run 'npm view @arcis/node version' directly.", DIM));
|
|
198
|
-
console.log();
|
|
199
|
-
process.exitCode = 2;
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const cur = parseVersion(current);
|
|
203
|
-
const lat = parseVersion(latest);
|
|
204
|
-
if (!cur || !lat) {
|
|
205
|
-
console.log(
|
|
206
|
-
` Installed @arcis/node ${current} ${c("(pre-release or unparseable)", DIM)}`
|
|
207
|
-
);
|
|
208
|
-
console.log(` Latest @arcis/node ${latest}`);
|
|
209
|
-
console.log();
|
|
210
|
-
console.log(c(" Skipping comparison \u2014 manually decide.", DIM));
|
|
211
|
-
console.log();
|
|
212
|
-
process.exitCode = 0;
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
if (versionCompare(cur, lat) >= 0) {
|
|
216
|
-
console.log(` Installed @arcis/node ${current}`);
|
|
217
|
-
console.log(` Latest @arcis/node ${latest}`);
|
|
218
|
-
console.log();
|
|
219
|
-
console.log(c(" You are on the latest version.", BOLD, GREEN));
|
|
220
|
-
console.log();
|
|
221
|
-
process.exitCode = 0;
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
console.log(` Installed @arcis/node ${current}`);
|
|
225
|
-
console.log(
|
|
226
|
-
` Latest ${c(`@arcis/node ${latest}`, BOLD)} ${c("(update available)", YELLOW)}`
|
|
227
|
-
);
|
|
228
|
-
console.log();
|
|
229
|
-
console.log(c(" Run to upgrade", BOLD));
|
|
230
|
-
console.log(` ${c("npm install @arcis/node@latest", GREEN)}`);
|
|
231
|
-
console.log();
|
|
232
|
-
if (!apply) {
|
|
233
|
-
console.log(c(" Or rerun: 'arcis update --apply' to upgrade in place.", DIM));
|
|
234
|
-
console.log();
|
|
235
|
-
process.exitCode = 1;
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (!yes && process.stdin.isTTY) {
|
|
239
|
-
process.stdout.write("Upgrade now? [y/N] ");
|
|
240
|
-
const response = await new Promise((res) => {
|
|
241
|
-
process.stdin.once("data", (chunk) => res(chunk.toString().trim().toLowerCase()));
|
|
242
|
-
});
|
|
243
|
-
if (!response.startsWith("y")) {
|
|
244
|
-
process.exitCode = 1;
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
249
|
-
console.log(` $ ${npmCmd} install @arcis/node@latest`);
|
|
250
|
-
const result = child_process.spawnSync(npmCmd, ["install", "@arcis/node@latest"], {
|
|
251
|
-
stdio: "inherit"
|
|
252
|
-
});
|
|
253
|
-
process.exitCode = result.status ?? 1;
|
|
254
|
-
}
|
|
255
|
-
async function main() {
|
|
256
|
-
const args = process.argv.slice(2);
|
|
257
|
-
if (args.length === 0) {
|
|
258
|
-
printCatalog(false);
|
|
259
|
-
process.exit(0);
|
|
260
|
-
}
|
|
261
|
-
const arg0 = args[0];
|
|
262
|
-
if (arg0 === "--list" || arg0 === "-l") {
|
|
263
|
-
printCatalog(true);
|
|
264
|
-
process.exit(0);
|
|
265
|
-
}
|
|
266
|
-
if (arg0 === "-h" || arg0 === "--help") {
|
|
267
|
-
printCatalog(false);
|
|
268
|
-
console.log(c(" Run 'arcis <command> --help' for full flags.", DIM));
|
|
269
|
-
console.log();
|
|
270
|
-
process.exit(0);
|
|
271
|
-
}
|
|
272
|
-
if (arg0 === "-V" || arg0 === "--version") {
|
|
273
|
-
console.log(getInstalledVersion());
|
|
274
|
-
process.exit(0);
|
|
275
|
-
}
|
|
276
|
-
if (arg0 === "update") {
|
|
277
|
-
await updateCommand(args.slice(1));
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
if (arg0 === "scan" || arg0 === "audit" || arg0 === "sca") {
|
|
281
|
-
if (!hasPythonArcis()) {
|
|
282
|
-
console.error(
|
|
283
|
-
c(
|
|
284
|
-
`arcis: '${arg0}' is implemented by the Python CLI. Install with:`,
|
|
285
|
-
YELLOW,
|
|
286
|
-
BOLD
|
|
287
|
-
)
|
|
288
|
-
);
|
|
289
|
-
console.error(" pip install arcis");
|
|
290
|
-
console.error();
|
|
291
|
-
console.error(c("Why: scan/audit/sca rely on Python's threat-DB and rule data.", DIM));
|
|
292
|
-
console.error(
|
|
293
|
-
c(
|
|
294
|
-
"@arcis/node implements the middleware + dashboard upload \u2014 see the docs.",
|
|
295
|
-
DIM
|
|
296
|
-
)
|
|
297
|
-
);
|
|
298
|
-
process.exit(127);
|
|
299
|
-
}
|
|
300
|
-
forwardToPython(args);
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
console.error(`arcis: unknown command '${arg0}'`);
|
|
304
|
-
console.error("Run 'arcis --list' for available commands.");
|
|
305
|
-
process.exit(1);
|
|
306
|
-
}
|
|
307
|
-
main().catch((err) => {
|
|
308
|
-
console.error(c(`arcis: unexpected error: ${err}`, RED));
|
|
309
|
-
process.exit(1);
|
|
310
|
-
});
|
|
311
|
-
//# sourceMappingURL=arcis.js.map
|
|
312
|
-
//# sourceMappingURL=arcis.js.map
|