@grackle-ai/web-server 0.115.2 → 0.117.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/dist/sandbox-csp.d.ts
CHANGED
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
* Ported from the T1 Storybook sidecar (`@grackle-ai/web-components`
|
|
5
5
|
* `mcp-app-sandbox/serve.mjs`) — kept in TS here so the production sandbox server
|
|
6
6
|
* can unit-test it. The CSP locks down the inner widget: `script-src 'self' blob:`
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* by default, widened only by the per-resource domain allowlists supplied via the
|
|
8
|
+
* `?csp=` query param (`McpUiResourceCsp`) and two explicit opt-in flags —
|
|
9
|
+
* `allowInlineScripts` (`'unsafe-inline'`, agent-authored HTML widgets, #1239) and
|
|
10
|
+
* `allowUnsafeEval` (`'unsafe-eval'`, the Grackle React runtime, #1268). Both are
|
|
11
|
+
* safe only because the sandbox is a separate origin (no `window.top`) with a
|
|
12
|
+
* restricted `connect-src`, so code runs isolated with no exfil path.
|
|
9
13
|
*/
|
|
10
14
|
/** Subset of MCP Apps `McpUiResourceCsp` honored by the sandbox CSP. */
|
|
11
15
|
export interface SandboxCsp {
|
|
@@ -20,6 +24,13 @@ export interface SandboxCsp {
|
|
|
20
24
|
* `connect-src`; inline scripts run only within the isolated widget origin.
|
|
21
25
|
*/
|
|
22
26
|
allowInlineScripts?: unknown;
|
|
27
|
+
/**
|
|
28
|
+
* Allow `eval`/`new Function` in the sandbox (`script-src 'unsafe-eval'`). Set for
|
|
29
|
+
* the Grackle React runtime (#1268), which transpiles + executes agent JSX via
|
|
30
|
+
* react-live (`new Function`). Safe for the same reason as `allowInlineScripts`:
|
|
31
|
+
* the sandbox is a separate origin with a restricted `connect-src` (no exfil).
|
|
32
|
+
*/
|
|
33
|
+
allowUnsafeEval?: unknown;
|
|
23
34
|
}
|
|
24
35
|
/**
|
|
25
36
|
* Build the `Content-Security-Policy` header value from an optional
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-csp.d.ts","sourceRoot":"","sources":["../src/sandbox-csp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sandbox-csp.d.ts","sourceRoot":"","sources":["../src/sandbox-csp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wEAAwE;AACxE,MAAM,WAAW,UAAU;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AA8BD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAoBlE"}
|
package/dist/sandbox-csp.js
CHANGED
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
* Ported from the T1 Storybook sidecar (`@grackle-ai/web-components`
|
|
5
5
|
* `mcp-app-sandbox/serve.mjs`) — kept in TS here so the production sandbox server
|
|
6
6
|
* can unit-test it. The CSP locks down the inner widget: `script-src 'self' blob:`
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* by default, widened only by the per-resource domain allowlists supplied via the
|
|
8
|
+
* `?csp=` query param (`McpUiResourceCsp`) and two explicit opt-in flags —
|
|
9
|
+
* `allowInlineScripts` (`'unsafe-inline'`, agent-authored HTML widgets, #1239) and
|
|
10
|
+
* `allowUnsafeEval` (`'unsafe-eval'`, the Grackle React runtime, #1268). Both are
|
|
11
|
+
* safe only because the sandbox is a separate origin (no `window.top`) with a
|
|
12
|
+
* restricted `connect-src`, so code runs isolated with no exfil path.
|
|
9
13
|
*/
|
|
10
14
|
/**
|
|
11
15
|
* Keep only entries that are bare http(s) origins (e.g. `http://127.0.0.1:7435`).
|
|
@@ -45,9 +49,10 @@ export function buildCspHeader(csp) {
|
|
|
45
49
|
const frameDomains = sanitizeCspDomains(csp?.frameDomains).join(" ");
|
|
46
50
|
const baseUriDomains = sanitizeCspDomains(csp?.baseUriDomains).join(" ");
|
|
47
51
|
const inlineScripts = csp?.allowInlineScripts === true ? " 'unsafe-inline'" : "";
|
|
52
|
+
const unsafeEval = csp?.allowUnsafeEval === true ? " 'unsafe-eval'" : "";
|
|
48
53
|
return [
|
|
49
54
|
"default-src 'self'",
|
|
50
|
-
`script-src 'self'${inlineScripts} blob: ${resourceDomains}`.trim(),
|
|
55
|
+
`script-src 'self'${inlineScripts}${unsafeEval} blob: ${resourceDomains}`.trim(),
|
|
51
56
|
`style-src 'self' 'unsafe-inline' blob: data: ${resourceDomains}`.trim(),
|
|
52
57
|
`img-src 'self' data: blob: ${resourceDomains}`.trim(),
|
|
53
58
|
`font-src 'self' data: blob: ${resourceDomains}`.trim(),
|
package/dist/sandbox-csp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-csp.js","sourceRoot":"","sources":["../src/sandbox-csp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sandbox-csp.js","sourceRoot":"","sources":["../src/sandbox-csp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAwBH;;;;;;;;;GASG;AACH,SAAS,kBAAkB,CAAC,OAAgB;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAQ,OAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE;QACtD,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;YACvB,+DAA+D;YAC/D,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC;QACrF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,GAA2B;IACxD,MAAM,eAAe,GAAW,kBAAkB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnF,MAAM,cAAc,GAAW,kBAAkB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,YAAY,GAAW,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7E,MAAM,cAAc,GAAW,kBAAkB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,aAAa,GAAW,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IACzF,MAAM,UAAU,GAAW,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,OAAO;QACL,oBAAoB;QACpB,oBAAoB,aAAa,GAAG,UAAU,UAAU,eAAe,EAAE,CAAC,IAAI,EAAE;QAChF,gDAAgD,eAAe,EAAE,CAAC,IAAI,EAAE;QACxE,8BAA8B,eAAe,EAAE,CAAC,IAAI,EAAE;QACtD,+BAA+B,eAAe,EAAE,CAAC,IAAI,EAAE;QACvD,gCAAgC,eAAe,EAAE,CAAC,IAAI,EAAE;QACxD,sBAAsB,cAAc,EAAE,CAAC,IAAI,EAAE;QAC7C,2BAA2B,eAAe,EAAE,CAAC,IAAI,EAAE;QACnD,YAAY,CAAC,CAAC,CAAC,aAAa,YAAY,EAAE,CAAC,CAAC,CAAC,kBAAkB;QAC/D,mBAAmB;QACnB,cAAc,CAAC,CAAC,CAAC,YAAY,cAAc,EAAE,CAAC,CAAC,CAAC,iBAAiB;KAClE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-server.d.ts","sourceRoot":"","sources":["../src/sandbox-server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"sandbox-server.d.ts","sourceRoot":"","sources":["../src/sandbox-server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;CACrB;AAgCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC,MAAM,CA8D9E"}
|
package/dist/sandbox-server.js
CHANGED
|
@@ -3,11 +3,25 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { buildCspHeader } from "./sandbox-csp.js";
|
|
5
5
|
const nodeRequire = createRequire(import.meta.url);
|
|
6
|
-
/** Read
|
|
7
|
-
function
|
|
8
|
-
const assetPath = nodeRequire.resolve(`@grackle-ai/web-components
|
|
6
|
+
/** Read an asset shipped in @grackle-ai/web-components (path relative to its package root). */
|
|
7
|
+
function readWebComponentsAsset(subpath) {
|
|
8
|
+
const assetPath = nodeRequire.resolve(`@grackle-ai/web-components/${subpath}`);
|
|
9
9
|
return readFileSync(assetPath, "utf-8");
|
|
10
10
|
}
|
|
11
|
+
/** Read a sandbox proxy asset (the static double-iframe relay) from web-components. */
|
|
12
|
+
function readSandboxAsset(subpath) {
|
|
13
|
+
return readWebComponentsAsset(`mcp-app-sandbox/${subpath}`);
|
|
14
|
+
}
|
|
15
|
+
// The React runtime bundle (#1268) is a BUILT artifact (vite), unlike the static
|
|
16
|
+
// sandbox proxy assets above. Read it lazily + cache so constructing the server
|
|
17
|
+
// never throws if web-components hasn't been built yet (e.g. isolated unit tests).
|
|
18
|
+
let cachedRuntimeBundle;
|
|
19
|
+
function readRuntimeBundle() {
|
|
20
|
+
if (cachedRuntimeBundle === undefined) {
|
|
21
|
+
cachedRuntimeBundle = readWebComponentsAsset("mcp-app-runtime/runtime.js");
|
|
22
|
+
}
|
|
23
|
+
return cachedRuntimeBundle;
|
|
24
|
+
}
|
|
11
25
|
const JS_HEADERS = {
|
|
12
26
|
"Content-Type": "text/javascript; charset=utf-8",
|
|
13
27
|
"Cache-Control": "no-cache, no-store, must-revalidate",
|
|
@@ -45,6 +59,20 @@ export function createSandboxServer(options) {
|
|
|
45
59
|
res.end(sandboxRelay);
|
|
46
60
|
return;
|
|
47
61
|
}
|
|
62
|
+
// The Grackle React runtime bundle (#1268), loaded as `script-src 'self'` by
|
|
63
|
+
// the inner widget bootstrap for `grackle-react` renders.
|
|
64
|
+
if (isGet && path === "/runtime.js") {
|
|
65
|
+
try {
|
|
66
|
+
const runtime = readRuntimeBundle();
|
|
67
|
+
res.writeHead(200, JS_HEADERS);
|
|
68
|
+
res.end(runtime);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
72
|
+
res.end("Runtime bundle not built.");
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
48
76
|
if (isGet && (path === "/" || path === "/sandbox.html")) {
|
|
49
77
|
let csp;
|
|
50
78
|
const cspParam = url.searchParams.get("csp");
|
|
@@ -67,7 +95,7 @@ export function createSandboxServer(options) {
|
|
|
67
95
|
return;
|
|
68
96
|
}
|
|
69
97
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
70
|
-
res.end("Only sandbox.html
|
|
98
|
+
res.end("Only sandbox.html, sandbox-relay.js and runtime.js are served on this port.");
|
|
71
99
|
});
|
|
72
100
|
}
|
|
73
101
|
//# sourceMappingURL=sandbox-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox-server.js","sourceRoot":"","sources":["../src/sandbox-server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAmB,MAAM,kBAAkB,CAAC;AAEnE,MAAM,WAAW,GAAgB,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAUhE
|
|
1
|
+
{"version":3,"file":"sandbox-server.js","sourceRoot":"","sources":["../src/sandbox-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grackle-ai/web-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.117.0",
|
|
4
4
|
"description": "HTTP web server for Grackle — static file serving, pairing, OAuth, and ConnectRPC proxy",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@connectrpc/connect": "^2.0.0",
|
|
33
33
|
"@connectrpc/connect-node": "^2.0.0",
|
|
34
|
-
"@grackle-ai/auth": "0.
|
|
35
|
-
"@grackle-ai/web": "0.
|
|
36
|
-
"@grackle-ai/web-components": "0.
|
|
34
|
+
"@grackle-ai/auth": "0.117.0",
|
|
35
|
+
"@grackle-ai/web": "0.117.0",
|
|
36
|
+
"@grackle-ai/web-components": "0.117.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@rushstack/heft": "1.2.7",
|