@sysid/sandbox-runtime-improved 0.0.50-sysid.1 → 0.0.52-sysid.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.
Files changed (48) hide show
  1. package/README.md +2 -2
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/sandbox/http-proxy.d.ts +21 -1
  6. package/dist/sandbox/http-proxy.d.ts.map +1 -1
  7. package/dist/sandbox/http-proxy.js +55 -5
  8. package/dist/sandbox/http-proxy.js.map +1 -1
  9. package/dist/sandbox/linux-sandbox-utils.d.ts +2 -0
  10. package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -1
  11. package/dist/sandbox/linux-sandbox-utils.js +3 -2
  12. package/dist/sandbox/linux-sandbox-utils.js.map +1 -1
  13. package/dist/sandbox/macos-sandbox-utils.d.ts +2 -0
  14. package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -1
  15. package/dist/sandbox/macos-sandbox-utils.js +2 -2
  16. package/dist/sandbox/macos-sandbox-utils.js.map +1 -1
  17. package/dist/sandbox/mitm-ca.d.ts +33 -16
  18. package/dist/sandbox/mitm-ca.d.ts.map +1 -1
  19. package/dist/sandbox/mitm-ca.js +124 -24
  20. package/dist/sandbox/mitm-ca.js.map +1 -1
  21. package/dist/sandbox/mitm-leaf.d.ts +28 -0
  22. package/dist/sandbox/mitm-leaf.d.ts.map +1 -0
  23. package/dist/sandbox/mitm-leaf.js +94 -0
  24. package/dist/sandbox/mitm-leaf.js.map +1 -0
  25. package/dist/sandbox/request-filter.d.ts +46 -0
  26. package/dist/sandbox/request-filter.d.ts.map +1 -0
  27. package/dist/sandbox/request-filter.js +106 -0
  28. package/dist/sandbox/request-filter.js.map +1 -0
  29. package/dist/sandbox/sandbox-config.d.ts +47 -26
  30. package/dist/sandbox/sandbox-config.d.ts.map +1 -1
  31. package/dist/sandbox/sandbox-config.js +21 -3
  32. package/dist/sandbox/sandbox-config.js.map +1 -1
  33. package/dist/sandbox/sandbox-manager.d.ts +2 -0
  34. package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
  35. package/dist/sandbox/sandbox-manager.js +143 -98
  36. package/dist/sandbox/sandbox-manager.js.map +1 -1
  37. package/dist/sandbox/sandbox-utils.d.ts +6 -1
  38. package/dist/sandbox/sandbox-utils.d.ts.map +1 -1
  39. package/dist/sandbox/sandbox-utils.js +24 -1
  40. package/dist/sandbox/sandbox-utils.js.map +1 -1
  41. package/dist/sandbox/socks-proxy.d.ts.map +1 -1
  42. package/dist/sandbox/socks-proxy.js +26 -9
  43. package/dist/sandbox/socks-proxy.js.map +1 -1
  44. package/dist/sandbox/tls-terminate-proxy.d.ts +70 -0
  45. package/dist/sandbox/tls-terminate-proxy.d.ts.map +1 -0
  46. package/dist/sandbox/tls-terminate-proxy.js +217 -0
  47. package/dist/sandbox/tls-terminate-proxy.js.map +1 -0
  48. package/package.json +7 -5
@@ -1,38 +1,126 @@
1
1
  /**
2
- * MITM CA loader for the in-process TLS-terminating proxy.
2
+ * MITM CA loader/generator for the in-process TLS-terminating proxy.
3
3
  *
4
- * Loads a user-provided CA cert + key from disk. The CA is supplied via
5
- * `network.tlsTerminate.{caCertPath,caKeyPath}` (see sandbox-config.ts).
6
- * SRT does not generate the CA itself TLS termination is opt-in and
7
- * requires the caller to provide both paths.
4
+ * The CA is supplied via `network.tlsTerminate.{caCertPath,caKeyPath}` (see
5
+ * sandbox-config.ts). If both paths are omitted, SRT generates an ephemeral
6
+ * RSA-2048 self-signed CA into a temp directory; the cert path is what the
7
+ * trust env vars point at. The caller is responsible for cleaning up via
8
+ * `disposeMitmCA()` (SandboxManager.reset() does this).
8
9
  */
9
- import { readFileSync } from 'node:fs';
10
+ import forge from 'node-forge';
11
+ import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
12
+ import { rm } from 'node:fs/promises';
13
+ import { tmpdir } from 'node:os';
14
+ import { join, dirname } from 'node:path';
10
15
  import { logForDebugging } from '../utils/debug.js';
11
- let ca;
16
+ const { pki, md, random, util } = forge;
12
17
  /**
13
- * Load the MITM CA from the given paths. Throws if either file is missing,
14
- * unreadable, or not PEM TLS termination is explicit opt-in, so a bad
15
- * config is a hard error (same posture as checkDependencies()).
18
+ * Create a MitmCA. If `caCertPath`/`caKeyPath` are provided, load from disk
19
+ * (throws if either file is missing, unreadable, not PEM, fails to parse, or
20
+ * the key is not RSA). If both are omitted, generate an ephemeral CA into a
21
+ * fresh temp directory.
16
22
  *
17
- * Idempotent: subsequent calls return the cached CA.
23
+ * Pure factory: no module-level state. The caller (SandboxManager) owns the
24
+ * returned object and its lifetime.
18
25
  */
19
- export function loadMitmCA(opts) {
20
- if (ca)
21
- return ca;
22
- const { caCertPath: certPath, caKeyPath: keyPath } = opts;
26
+ export function createMitmCA(opts) {
27
+ if (opts.caCertPath && opts.caKeyPath) {
28
+ return loadCA(opts.caCertPath, opts.caKeyPath);
29
+ }
30
+ if (opts.caCertPath || opts.caKeyPath) {
31
+ throw new Error('tlsTerminate: caCertPath and caKeyPath must be provided together');
32
+ }
33
+ return generateEphemeralCA();
34
+ }
35
+ /** Remove the temp directory for an SRT-generated CA. No-op for user CAs. */
36
+ export async function disposeMitmCA(ca) {
37
+ if (!ca.ephemeral)
38
+ return;
39
+ try {
40
+ await rm(dirname(ca.certPath), { recursive: true, force: true });
41
+ }
42
+ catch (err) {
43
+ logForDebugging(`[mitm-ca] cleanup failed: ${err.message}`, {
44
+ level: 'warn',
45
+ });
46
+ }
47
+ }
48
+ function loadCA(certPath, keyPath) {
23
49
  const certPem = readPem(certPath, 'CERTIFICATE', 'tlsTerminate.caCertPath');
24
50
  const keyPem = readPem(keyPath, 'PRIVATE KEY', 'tlsTerminate.caKeyPath');
25
- ca = { certPath, keyPath, certPem, keyPem };
51
+ let cert;
52
+ let key;
53
+ try {
54
+ cert = pki.certificateFromPem(certPem);
55
+ key = pki.privateKeyFromPem(keyPem);
56
+ }
57
+ catch (err) {
58
+ throw new Error(`tlsTerminate: failed to parse CA from ${certPath}: ` +
59
+ err.message);
60
+ }
61
+ if (!('n' in key) || !('d' in key)) {
62
+ // node-forge can only sign with RSA private keys.
63
+ throw new Error(`tlsTerminate.caKeyPath: CA key at ${keyPath} must be RSA`);
64
+ }
26
65
  logForDebugging(`[mitm-ca] loaded CA from ${certPath}`);
27
- return ca;
28
- }
29
- /** Return the cached CA, or undefined if tlsTerminate was not configured. */
30
- export function getMitmCA() {
31
- return ca;
66
+ return {
67
+ certPath,
68
+ keyPath,
69
+ certPem,
70
+ keyPem,
71
+ cert,
72
+ key: key,
73
+ leafCerts: new Map(),
74
+ secureContexts: new Map(),
75
+ ephemeral: false,
76
+ };
32
77
  }
33
- /** Clear the cached CA — for tests / config reload. */
34
- export function resetMitmCA() {
35
- ca = undefined;
78
+ function generateEphemeralCA() {
79
+ const keys = pki.rsa.generateKeyPair(2048);
80
+ const cert = pki.createCertificate();
81
+ cert.publicKey = keys.publicKey;
82
+ cert.serialNumber = randomSerial();
83
+ cert.validity.notBefore = daysFromNow(-1);
84
+ cert.validity.notAfter = daysFromNow(825);
85
+ const subject = [
86
+ { name: 'commonName', value: 'sandbox-runtime ephemeral CA' },
87
+ { name: 'organizationName', value: 'sandbox-runtime' },
88
+ ];
89
+ cert.setSubject(subject);
90
+ cert.setIssuer(subject);
91
+ cert.setExtensions([
92
+ { name: 'basicConstraints', cA: true, critical: true },
93
+ {
94
+ name: 'keyUsage',
95
+ critical: true,
96
+ keyCertSign: true,
97
+ cRLSign: true,
98
+ digitalSignature: true,
99
+ },
100
+ { name: 'subjectKeyIdentifier' },
101
+ ]);
102
+ cert.sign(keys.privateKey, md.sha256.create());
103
+ const certPem = pki.certificateToPem(cert);
104
+ const keyPem = pki.privateKeyToPem(keys.privateKey);
105
+ // Write to disk so trust env vars (NODE_EXTRA_CA_CERTS etc.) can point at
106
+ // a real path. mkdtemp gives us an unguessable per-process directory.
107
+ const dir = mkdtempSync(join(tmpdir(), 'srt-ca-'));
108
+ const certPath = join(dir, 'ca.crt');
109
+ const keyPath = join(dir, 'ca.key');
110
+ writeFileSync(certPath, certPem, { mode: 0o644 });
111
+ writeFileSync(keyPath, keyPem, { mode: 0o600 });
112
+ logForDebugging(`[mitm-ca] generated ephemeral CA at ${certPath}`);
113
+ return {
114
+ certPath,
115
+ keyPath,
116
+ certPem,
117
+ keyPem,
118
+ cert,
119
+ key: keys.privateKey,
120
+ leafCerts: new Map(),
121
+ secureContexts: new Map(),
122
+ ephemeral: true,
123
+ };
36
124
  }
37
125
  function readPem(path, label, field) {
38
126
  let pem;
@@ -50,4 +138,16 @@ function readPem(path, label, field) {
50
138
  }
51
139
  return pem;
52
140
  }
141
+ function randomSerial() {
142
+ // 16 random bytes, high bit cleared so the DER INTEGER stays positive.
143
+ const bytes = random.getBytesSync(16);
144
+ const hex = util.bytesToHex(bytes);
145
+ const firstNibble = parseInt(hex[0], 16) & 0x7;
146
+ return firstNibble.toString(16) + hex.slice(1);
147
+ }
148
+ function daysFromNow(days) {
149
+ const d = new Date();
150
+ d.setDate(d.getDate() + days);
151
+ return d;
152
+ }
53
153
  //# sourceMappingURL=mitm-ca.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mitm-ca.js","sourceRoot":"","sources":["../../src/sandbox/mitm-ca.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AASnD,IAAI,EAAsB,CAAA;AAE1B;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAG1B;IACC,IAAI,EAAE;QAAE,OAAO,EAAE,CAAA;IAEjB,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAEzD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,yBAAyB,CAAC,CAAA;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,wBAAwB,CAAC,CAAA;IAExE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IAC3C,eAAe,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAA;IACvD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,SAAS;IACvB,OAAO,EAAE,CAAA;AACX,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,WAAW;IACzB,EAAE,GAAG,SAAS,CAAA;AAChB,CAAC;AAED,SAAS,OAAO,CAAC,IAAY,EAAE,KAAa,EAAE,KAAa;IACzD,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,CAAA;QAC/D,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,iBAAiB,IAAI,KAAK,IAAI,GAAG,CAAC,CAAA;IAC5D,CAAC;IACD,+EAA+E;IAC/E,sCAAsC;IACtC,IAAI,CAAC,IAAI,MAAM,CAAC,qBAAqB,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,KAAK,IAAI,iBAAiB,KAAK,EAAE,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"mitm-ca.js","sourceRoot":"","sources":["../../src/sandbox/mitm-ca.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Per-host leaf certificate minter for the in-process TLS-terminating proxy.
3
+ *
4
+ * Given a MitmCA (see mitm-ca.ts), mints a leaf certificate for a specific
5
+ * hostname on first use and caches it for the lifetime of that CA instance.
6
+ * The leaf is signed by the CA and carries SAN=DNS:<host> (or IP:<addr>),
7
+ * so a client that trusts the CA will accept it for that host.
8
+ */
9
+ import { type SecureContext } from 'node:tls';
10
+ import type { MitmCA } from './mitm-ca.js';
11
+ export type LeafCert = {
12
+ /** Leaf cert PEM followed by the CA cert PEM (full chain). */
13
+ certPem: string;
14
+ /** Leaf private key PEM. */
15
+ keyPem: string;
16
+ };
17
+ /**
18
+ * Mint (or return cached) an RSA-2048 leaf cert for `hostname`, signed by `ca`.
19
+ * The cache lives on `ca.leafCerts`.
20
+ */
21
+ export declare function mintLeafCert(ca: MitmCA, hostname: string): LeafCert;
22
+ /**
23
+ * Mint-or-cache a Node TLS SecureContext for `hostname`. Intended as the
24
+ * SNICallback target in the terminating proxy. The cache lives on
25
+ * `ca.secureContexts`.
26
+ */
27
+ export declare function secureContextFor(ca: MitmCA, hostname: string): SecureContext;
28
+ //# sourceMappingURL=mitm-leaf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mitm-leaf.d.ts","sourceRoot":"","sources":["../../src/sandbox/mitm-leaf.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AAElE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAI1C,MAAM,MAAM,QAAQ,GAAG;IACrB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAsCnE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAO5E"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Per-host leaf certificate minter for the in-process TLS-terminating proxy.
3
+ *
4
+ * Given a MitmCA (see mitm-ca.ts), mints a leaf certificate for a specific
5
+ * hostname on first use and caches it for the lifetime of that CA instance.
6
+ * The leaf is signed by the CA and carries SAN=DNS:<host> (or IP:<addr>),
7
+ * so a client that trusts the CA will accept it for that host.
8
+ */
9
+ import forge from 'node-forge';
10
+ import { isIP } from 'node:net';
11
+ import { createSecureContext } from 'node:tls';
12
+ import { logForDebugging } from '../utils/debug.js';
13
+ const { pki, md, random, util } = forge;
14
+ /**
15
+ * Mint (or return cached) an RSA-2048 leaf cert for `hostname`, signed by `ca`.
16
+ * The cache lives on `ca.leafCerts`.
17
+ */
18
+ export function mintLeafCert(ca, hostname) {
19
+ const cached = ca.leafCerts.get(hostname);
20
+ if (cached)
21
+ return cached;
22
+ const keys = pki.rsa.generateKeyPair(2048);
23
+ const cert = pki.createCertificate();
24
+ cert.publicKey = keys.publicKey;
25
+ cert.serialNumber = randomSerial();
26
+ cert.validity.notBefore = daysFromNow(-1);
27
+ cert.validity.notAfter = clampValidity(ca.cert);
28
+ cert.setSubject([{ name: 'commonName', value: hostname }]);
29
+ cert.setIssuer(ca.cert.subject.attributes);
30
+ cert.setExtensions([
31
+ { name: 'basicConstraints', cA: false, critical: true },
32
+ {
33
+ name: 'keyUsage',
34
+ critical: true,
35
+ digitalSignature: true,
36
+ keyEncipherment: true,
37
+ },
38
+ { name: 'extKeyUsage', serverAuth: true },
39
+ { name: 'subjectAltName', altNames: [sanFor(hostname)] },
40
+ // No authorityKeyIdentifier: node-forge stores SKI as a hex string for
41
+ // in-memory certs (e.g. the ephemeral CA) but as raw bytes for certs
42
+ // parsed from PEM (e.g. a user-supplied CA). Passing the hex string as
43
+ // keyIdentifier produces an AKI that doesn't match the CA's SKI and
44
+ // chain verification fails. AKI is optional — issuer/subject DN match
45
+ // is sufficient — so omit it.
46
+ ]);
47
+ cert.sign(ca.key, md.sha256.create());
48
+ const leaf = {
49
+ certPem: pki.certificateToPem(cert) + ca.certPem,
50
+ keyPem: pki.privateKeyToPem(keys.privateKey),
51
+ };
52
+ ca.leafCerts.set(hostname, leaf);
53
+ logForDebugging(`[mitm-leaf] minted RSA leaf for ${hostname}`);
54
+ return leaf;
55
+ }
56
+ /**
57
+ * Mint-or-cache a Node TLS SecureContext for `hostname`. Intended as the
58
+ * SNICallback target in the terminating proxy. The cache lives on
59
+ * `ca.secureContexts`.
60
+ */
61
+ export function secureContextFor(ca, hostname) {
62
+ const cached = ca.secureContexts.get(hostname);
63
+ if (cached)
64
+ return cached;
65
+ const { certPem, keyPem } = mintLeafCert(ca, hostname);
66
+ const ctx = createSecureContext({ cert: certPem, key: keyPem });
67
+ ca.secureContexts.set(hostname, ctx);
68
+ return ctx;
69
+ }
70
+ function sanFor(hostname) {
71
+ // RFC 5280 GeneralName tags: 2 = dNSName, 7 = iPAddress.
72
+ return isIP(hostname) !== 0
73
+ ? { type: 7, ip: hostname }
74
+ : { type: 2, value: hostname };
75
+ }
76
+ /** Leaf validity capped at min(CA notAfter, now+825d) per CA/B baseline. */
77
+ function clampValidity(caCert) {
78
+ const caEnd = caCert.validity.notAfter;
79
+ const max = daysFromNow(825);
80
+ return caEnd < max ? new Date(caEnd) : max;
81
+ }
82
+ function randomSerial() {
83
+ // 16 random bytes, high bit cleared so the DER INTEGER stays positive.
84
+ const bytes = random.getBytesSync(16);
85
+ const hex = util.bytesToHex(bytes);
86
+ const firstNibble = parseInt(hex[0], 16) & 0x7;
87
+ return firstNibble.toString(16) + hex.slice(1);
88
+ }
89
+ function daysFromNow(days) {
90
+ const d = new Date();
91
+ d.setDate(d.getDate() + days);
92
+ return d;
93
+ }
94
+ //# sourceMappingURL=mitm-leaf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mitm-leaf.js","sourceRoot":"","sources":["../../src/sandbox/mitm-leaf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Request-level filter hook for the forward proxy.
3
+ *
4
+ * Library consumers supply a `filterRequest` callback via
5
+ * `network.filterRequest`. It receives the parsed HTTP request (web-standard
6
+ * `Request`) and returns a decision. Applies to plain HTTP through the proxy
7
+ * and, when `tlsTerminate` is configured, to terminated HTTPS. The proxy
8
+ * enforces the decision; the library does not bless any matching DSL.
9
+ */
10
+ import type { IncomingMessage, ServerResponse } from 'node:http';
11
+ import { Readable } from 'node:stream';
12
+ export type RequestDecision = {
13
+ action: 'allow' | 'deny';
14
+ /**
15
+ * Human-readable reason. For denials this is surfaced to the sandboxed
16
+ * client in the response body so the agent can tell a policy block from a
17
+ * network failure.
18
+ */
19
+ reason?: string;
20
+ };
21
+ /**
22
+ * Called once per HTTP request that the proxy parses.
23
+ *
24
+ * - `request` is a web-standard `Request`: method, URL, headers, and a lazy
25
+ * `request.body` stream (one branch of a tee — reading it does not consume
26
+ * the bytes that get forwarded upstream). `request.signal` aborts when the
27
+ * client disconnects.
28
+ * - **Throwing or rejecting denies the request.** This is the failure
29
+ * contract for a security boundary: a buggy policy fails closed.
30
+ */
31
+ export type FilterRequestCallback = (request: Request) => Promise<RequestDecision>;
32
+ /**
33
+ * Build a `Request`, run the callback, and if denied write the 403 response
34
+ * and return `null`. On allow, returns the body stream the caller must pipe
35
+ * upstream — this is the original `IncomingMessage` when no tee was needed
36
+ * (GET/HEAD/OPTIONS), or the upstream-side branch of the tee otherwise.
37
+ * Callers must pipe the returned stream (not `req`) to the outbound request.
38
+ *
39
+ * For methods that carry a body, `req` is converted to a web stream and
40
+ * `tee()`'d: one branch goes to the callback's `Request.body`, the other is
41
+ * returned for the caller to forward. If the callback never reads its
42
+ * branch, we cancel it after the decision so the tee does not buffer the
43
+ * entire upload.
44
+ */
45
+ export declare function decideAndRespond(filterRequest: FilterRequestCallback, req: IncomingMessage, res: ServerResponse, url: string, signal: AbortSignal): Promise<Readable | null>;
46
+ //# sourceMappingURL=request-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-filter.d.ts","sourceRoot":"","sources":["../../src/sandbox/request-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGtC,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,OAAO,KACb,OAAO,CAAC,eAAe,CAAC,CAAA;AAI7B;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,qBAAqB,EACpC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAsD1B"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Request-level filter hook for the forward proxy.
3
+ *
4
+ * Library consumers supply a `filterRequest` callback via
5
+ * `network.filterRequest`. It receives the parsed HTTP request (web-standard
6
+ * `Request`) and returns a decision. Applies to plain HTTP through the proxy
7
+ * and, when `tlsTerminate` is configured, to terminated HTTPS. The proxy
8
+ * enforces the decision; the library does not bless any matching DSL.
9
+ */
10
+ import { Readable } from 'node:stream';
11
+ import { logForDebugging } from '../utils/debug.js';
12
+ const BODYLESS_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
13
+ /**
14
+ * Build a `Request`, run the callback, and if denied write the 403 response
15
+ * and return `null`. On allow, returns the body stream the caller must pipe
16
+ * upstream — this is the original `IncomingMessage` when no tee was needed
17
+ * (GET/HEAD/OPTIONS), or the upstream-side branch of the tee otherwise.
18
+ * Callers must pipe the returned stream (not `req`) to the outbound request.
19
+ *
20
+ * For methods that carry a body, `req` is converted to a web stream and
21
+ * `tee()`'d: one branch goes to the callback's `Request.body`, the other is
22
+ * returned for the caller to forward. If the callback never reads its
23
+ * branch, we cancel it after the decision so the tee does not buffer the
24
+ * entire upload.
25
+ */
26
+ export async function decideAndRespond(filterRequest, req, res, url, signal) {
27
+ let forCallback;
28
+ let forUpstream = req;
29
+ if (!BODYLESS_METHODS.has(req.method ?? 'GET')) {
30
+ const web = Readable.toWeb(req);
31
+ const [a, b] = web.tee();
32
+ forCallback = a;
33
+ forUpstream = Readable.fromWeb(b);
34
+ }
35
+ let webReq;
36
+ try {
37
+ webReq = new Request(url, {
38
+ method: req.method,
39
+ headers: incomingHeaders(req),
40
+ signal,
41
+ ...(forCallback ? { body: forCallback, duplex: 'half' } : {}),
42
+ });
43
+ }
44
+ catch (err) {
45
+ // Malformed URL/headers from the client — deny rather than crash.
46
+ deny(res, {
47
+ action: 'deny',
48
+ reason: `malformed request: ${err.message}`,
49
+ });
50
+ void forCallback?.cancel();
51
+ forUpstream.destroy();
52
+ return null;
53
+ }
54
+ let decision;
55
+ try {
56
+ decision = await filterRequest(webReq);
57
+ }
58
+ catch (err) {
59
+ decision = {
60
+ action: 'deny',
61
+ reason: `filterRequest threw: ${err.message}`,
62
+ };
63
+ }
64
+ // If the callback didn't read its branch, cancel it so tee() stops
65
+ // buffering bytes nobody will consume. If it did, the tee already buffered
66
+ // whatever was read; the upstream branch sees the same bytes.
67
+ if (forCallback && !webReq.bodyUsed) {
68
+ void forCallback.cancel();
69
+ }
70
+ if (decision.action === 'allow') {
71
+ logForDebugging(`[request-filter] allow ${req.method} ${url}`);
72
+ return forUpstream;
73
+ }
74
+ deny(res, decision);
75
+ forUpstream.destroy();
76
+ return null;
77
+ }
78
+ function deny(res, decision) {
79
+ const reason = decision.reason ?? 'denied by filterRequest';
80
+ logForDebugging(`[request-filter] deny: ${reason}`);
81
+ if (res.headersSent) {
82
+ res.destroy();
83
+ return;
84
+ }
85
+ res.writeHead(403, {
86
+ 'Content-Type': 'text/plain',
87
+ 'X-Proxy-Error': 'blocked-by-sandbox-runtime',
88
+ });
89
+ res.end(reason + '\n');
90
+ }
91
+ function incomingHeaders(req) {
92
+ const h = new Headers();
93
+ for (const [k, v] of Object.entries(req.headers)) {
94
+ if (v === undefined)
95
+ continue;
96
+ if (Array.isArray(v)) {
97
+ for (const vv of v)
98
+ h.append(k, vv);
99
+ }
100
+ else {
101
+ h.append(k, v);
102
+ }
103
+ }
104
+ return h;
105
+ }
106
+ //# sourceMappingURL=request-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-filter.js","sourceRoot":"","sources":["../../src/sandbox/request-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AA0BnD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;AAE5D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,aAAoC,EACpC,GAAoB,EACpB,GAAmB,EACnB,GAAW,EACX,MAAmB;IAEnB,IAAI,WAAmD,CAAA;IACvD,IAAI,WAAW,GAAa,GAAG,CAAA;IAC/B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAA+B,CAAA;QAC7D,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAA;QACxB,WAAW,GAAG,CAAC,CAAA;QACf,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC;IAED,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC;YAC7B,MAAM;YACN,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvE,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,kEAAkE;QAClE,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,sBAAuB,GAAa,CAAC,OAAO,EAAE;SACvD,CAAC,CAAA;QACF,KAAK,WAAW,EAAE,MAAM,EAAE,CAAA;QAC1B,WAAW,CAAC,OAAO,EAAE,CAAA;QACrB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,QAAyB,CAAA;IAC7B,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,GAAG;YACT,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,wBAAyB,GAAa,CAAC,OAAO,EAAE;SACzD,CAAA;IACH,CAAC;IAED,mEAAmE;IACnE,2EAA2E;IAC3E,8DAA8D;IAC9D,IAAI,WAAW,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpC,KAAK,WAAW,CAAC,MAAM,EAAE,CAAA;IAC3B,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAChC,eAAe,CAAC,0BAA0B,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC,CAAA;QAC9D,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACnB,WAAW,CAAC,OAAO,EAAE,CAAA;IACrB,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,IAAI,CAAC,GAAmB,EAAE,QAAyB;IAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,yBAAyB,CAAA;IAC3D,eAAe,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAA;IACnD,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,GAAG,CAAC,OAAO,EAAE,CAAA;QACb,OAAM;IACR,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,YAAY;QAC5B,eAAe,EAAE,4BAA4B;KAC9C,CAAC,CAAA;IACF,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;AACxB,CAAC;AAED,SAAS,eAAe,CAAC,GAAoB;IAC3C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAA;IACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,KAAK,SAAS;YAAE,SAAQ;QAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,KAAK,MAAM,EAAE,IAAI,CAAC;gBAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrC,CAAC;aAAM,CAAC;YACN,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
@@ -2,6 +2,7 @@
2
2
  * Configuration for Sandbox Runtime
3
3
  * This is the main configuration interface that consumers pass to SandboxManager.initialize()
4
4
  */
5
+ import type { FilterRequestCallback } from './request-filter.js';
5
6
  import { z } from 'zod';
6
7
  /**
7
8
  * Schema for MITM proxy configuration
@@ -57,15 +58,22 @@ export declare const NetworkConfigSchema: z.ZodObject<{
57
58
  socketPath: string;
58
59
  domains: string[];
59
60
  }>>;
60
- tlsTerminate: z.ZodOptional<z.ZodObject<{
61
- caCertPath: z.ZodString;
62
- caKeyPath: z.ZodString;
61
+ filterRequest: z.ZodOptional<z.ZodType<FilterRequestCallback, z.ZodTypeDef, FilterRequestCallback>>;
62
+ tlsTerminate: z.ZodOptional<z.ZodEffects<z.ZodObject<{
63
+ caCertPath: z.ZodOptional<z.ZodString>;
64
+ caKeyPath: z.ZodOptional<z.ZodString>;
63
65
  }, "strip", z.ZodTypeAny, {
64
- caCertPath: string;
65
- caKeyPath: string;
66
+ caCertPath?: string | undefined;
67
+ caKeyPath?: string | undefined;
66
68
  }, {
67
- caCertPath: string;
68
- caKeyPath: string;
69
+ caCertPath?: string | undefined;
70
+ caKeyPath?: string | undefined;
71
+ }>, {
72
+ caCertPath?: string | undefined;
73
+ caKeyPath?: string | undefined;
74
+ }, {
75
+ caCertPath?: string | undefined;
76
+ caKeyPath?: string | undefined;
69
77
  }>>;
70
78
  parentProxy: z.ZodOptional<z.ZodObject<{
71
79
  http: z.ZodOptional<z.ZodString>;
@@ -93,9 +101,10 @@ export declare const NetworkConfigSchema: z.ZodObject<{
93
101
  socketPath: string;
94
102
  domains: string[];
95
103
  } | undefined;
104
+ filterRequest?: FilterRequestCallback | undefined;
96
105
  tlsTerminate?: {
97
- caCertPath: string;
98
- caKeyPath: string;
106
+ caCertPath?: string | undefined;
107
+ caKeyPath?: string | undefined;
99
108
  } | undefined;
100
109
  parentProxy?: {
101
110
  http?: string | undefined;
@@ -115,9 +124,10 @@ export declare const NetworkConfigSchema: z.ZodObject<{
115
124
  socketPath: string;
116
125
  domains: string[];
117
126
  } | undefined;
127
+ filterRequest?: FilterRequestCallback | undefined;
118
128
  tlsTerminate?: {
119
- caCertPath: string;
120
- caKeyPath: string;
129
+ caCertPath?: string | undefined;
130
+ caKeyPath?: string | undefined;
121
131
  } | undefined;
122
132
  parentProxy?: {
123
133
  http?: string | undefined;
@@ -204,15 +214,22 @@ export declare const SandboxRuntimeConfigSchema: z.ZodObject<{
204
214
  socketPath: string;
205
215
  domains: string[];
206
216
  }>>;
207
- tlsTerminate: z.ZodOptional<z.ZodObject<{
208
- caCertPath: z.ZodString;
209
- caKeyPath: z.ZodString;
217
+ filterRequest: z.ZodOptional<z.ZodType<FilterRequestCallback, z.ZodTypeDef, FilterRequestCallback>>;
218
+ tlsTerminate: z.ZodOptional<z.ZodEffects<z.ZodObject<{
219
+ caCertPath: z.ZodOptional<z.ZodString>;
220
+ caKeyPath: z.ZodOptional<z.ZodString>;
210
221
  }, "strip", z.ZodTypeAny, {
211
- caCertPath: string;
212
- caKeyPath: string;
222
+ caCertPath?: string | undefined;
223
+ caKeyPath?: string | undefined;
224
+ }, {
225
+ caCertPath?: string | undefined;
226
+ caKeyPath?: string | undefined;
227
+ }>, {
228
+ caCertPath?: string | undefined;
229
+ caKeyPath?: string | undefined;
213
230
  }, {
214
- caCertPath: string;
215
- caKeyPath: string;
231
+ caCertPath?: string | undefined;
232
+ caKeyPath?: string | undefined;
216
233
  }>>;
217
234
  parentProxy: z.ZodOptional<z.ZodObject<{
218
235
  http: z.ZodOptional<z.ZodString>;
@@ -240,9 +257,10 @@ export declare const SandboxRuntimeConfigSchema: z.ZodObject<{
240
257
  socketPath: string;
241
258
  domains: string[];
242
259
  } | undefined;
260
+ filterRequest?: FilterRequestCallback | undefined;
243
261
  tlsTerminate?: {
244
- caCertPath: string;
245
- caKeyPath: string;
262
+ caCertPath?: string | undefined;
263
+ caKeyPath?: string | undefined;
246
264
  } | undefined;
247
265
  parentProxy?: {
248
266
  http?: string | undefined;
@@ -262,9 +280,10 @@ export declare const SandboxRuntimeConfigSchema: z.ZodObject<{
262
280
  socketPath: string;
263
281
  domains: string[];
264
282
  } | undefined;
283
+ filterRequest?: FilterRequestCallback | undefined;
265
284
  tlsTerminate?: {
266
- caCertPath: string;
267
- caKeyPath: string;
285
+ caCertPath?: string | undefined;
286
+ caKeyPath?: string | undefined;
268
287
  } | undefined;
269
288
  parentProxy?: {
270
289
  http?: string | undefined;
@@ -336,9 +355,10 @@ export declare const SandboxRuntimeConfigSchema: z.ZodObject<{
336
355
  socketPath: string;
337
356
  domains: string[];
338
357
  } | undefined;
358
+ filterRequest?: FilterRequestCallback | undefined;
339
359
  tlsTerminate?: {
340
- caCertPath: string;
341
- caKeyPath: string;
360
+ caCertPath?: string | undefined;
361
+ caKeyPath?: string | undefined;
342
362
  } | undefined;
343
363
  parentProxy?: {
344
364
  http?: string | undefined;
@@ -384,9 +404,10 @@ export declare const SandboxRuntimeConfigSchema: z.ZodObject<{
384
404
  socketPath: string;
385
405
  domains: string[];
386
406
  } | undefined;
407
+ filterRequest?: FilterRequestCallback | undefined;
387
408
  tlsTerminate?: {
388
- caCertPath: string;
389
- caKeyPath: string;
409
+ caCertPath?: string | undefined;
410
+ caKeyPath?: string | undefined;
390
411
  } | undefined;
391
412
  parentProxy?: {
392
413
  http?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox-config.d.ts","sourceRoot":"","sources":["../../src/sandbox/sandbox-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAgEvB;;;GAGG;AACH,QAAA,MAAM,qBAAqB;;;;;;;;;EAQzB,CAAA;AAEF;;;;GAIG;AACH,QAAA,MAAM,uBAAuB;;;;;;;;;;;;EAoB3B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwF9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;EAqBjC,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,2DAItC,CAAA;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAY9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;EAa9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DrC,CAAA;AAGF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AACrE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAA;AACD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAA"}
1
+ {"version":3,"file":"sandbox-config.d.ts","sourceRoot":"","sources":["../../src/sandbox/sandbox-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAGhE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAgEvB;;;GAGG;AACH,QAAA,MAAM,qBAAqB;;;;;;;;;EAQzB,CAAA;AAEF;;;;GAIG;AACH,QAAA,MAAM,uBAAuB;;;;;;;;;;;;EAoB3B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4G9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;EAqBjC,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,2DAItC,CAAA;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAY9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;EAa9B,CAAA;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DrC,CAAA;AAGF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AACrE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAA;AACD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAA"}