@imenam/mcp-gui-interface 1.0.13 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/src/request-guard.js +22 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -304,6 +304,8 @@ The guard refuses with a `403` JSON body `{ error }`:
|
|
|
304
304
|
| **Host** | a `Host` header other than `localhost`, `127.0.0.1` or `::1` | DNS rebinding: a hostile domain resolving to 127.0.0.1 |
|
|
305
305
|
| **Cross-site modification** | a method other than GET/HEAD/OPTIONS with `Sec-Fetch-Site` other than `same-origin`/`none`; when that header is absent, an `Origin` whose hostname is neither this machine's (hostname, interface addresses, loopback), nor the proxy's, nor in `trustedOrigins` | CSRF: a web page submitting a form or a `fetch` to the GUI |
|
|
306
306
|
|
|
307
|
+
When the network interfaces cannot be listed (a systemd sandbox with `RestrictAddressFamilies` lacking `AF_NETLINK`), the guard logs a warning and does not trust this machine's IP addresses as origins; list them in `trustedOrigins` if the GUI is opened through them over plain HTTP.
|
|
308
|
+
|
|
307
309
|
Requests carrying neither `Sec-Fetch-Site` nor `Origin` (curl, scripts) pass the second rule. Reads are never refused on their origin: without CORS headers, the browser does not let another site read the responses. Do not add a CORS middleware to a GUI worker.
|
|
308
310
|
|
|
309
311
|
**`GuiRequestGuardOptions`**
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* `trustedOrigins`. Requests without either header (curl, scripts) pass.
|
|
21
21
|
*/
|
|
22
22
|
import os from "node:os";
|
|
23
|
+
import { createLogger } from "./logger.js";
|
|
23
24
|
/** Interface every GUI worker binds to. */
|
|
24
25
|
export const GUI_LISTEN_HOST = "127.0.0.1";
|
|
25
26
|
const LOOPBACK_HOSTNAMES = ["localhost", "127.0.0.1", "::1"];
|
|
@@ -48,6 +49,25 @@ function originHostname(origin) {
|
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
51
|
}
|
|
52
|
+
const logger = createLogger("GuiRequestGuard");
|
|
53
|
+
/**
|
|
54
|
+
* Addresses of this machine's network interfaces. A sandbox that forbids
|
|
55
|
+
* netlink sockets (systemd `RestrictAddressFamilies` without `AF_NETLINK`)
|
|
56
|
+
* makes the listing fail: the addresses are then not trusted, and a warning
|
|
57
|
+
* says so.
|
|
58
|
+
*/
|
|
59
|
+
function interfaceAddresses() {
|
|
60
|
+
let interfaces;
|
|
61
|
+
try {
|
|
62
|
+
interfaces = os.networkInterfaces();
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
logger.warn(`Network interfaces cannot be listed (${error instanceof Error ? error.message : String(error)}): ` +
|
|
66
|
+
"origins using this machine's IP addresses are not trusted; list them in trustedOrigins if needed.");
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
return Object.values(interfaces).flatMap((addresses) => (addresses ?? []).map((address) => address.address.toLowerCase()));
|
|
70
|
+
}
|
|
51
71
|
/**
|
|
52
72
|
* Hostnames an `Origin` may carry: loopback names, this machine's hostname and
|
|
53
73
|
* interface addresses, the proxy's hostname and those of `trustedOrigins`.
|
|
@@ -55,10 +75,8 @@ function originHostname(origin) {
|
|
|
55
75
|
export function trustedOriginHostnames(options = {}) {
|
|
56
76
|
const names = new Set(LOOPBACK_HOSTNAMES);
|
|
57
77
|
names.add(os.hostname().toLowerCase());
|
|
58
|
-
for (const
|
|
59
|
-
|
|
60
|
-
names.add(address.address.toLowerCase());
|
|
61
|
-
}
|
|
78
|
+
for (const address of interfaceAddresses())
|
|
79
|
+
names.add(address);
|
|
62
80
|
const proxyUrl = options.proxyUrl ?? process.env.PROXY_URL;
|
|
63
81
|
for (const origin of [proxyUrl, ...(options.trustedOrigins ?? [])]) {
|
|
64
82
|
const hostname = origin ? originHostname(origin) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imenam/mcp-gui-interface",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Shared library for MCP GUI lifecycle management — spawning, IPC, proxy registration, logging, request guard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
],
|
|
35
35
|
"repository": {
|
|
36
36
|
"type": "git",
|
|
37
|
-
"url": "https://github.com/Matthieu-Pesnot-Pin/mcp-gui-interface.git"
|
|
37
|
+
"url": "git+https://github.com/Matthieu-Pesnot-Pin/mcp-gui-interface.git"
|
|
38
38
|
},
|
|
39
39
|
"author": "Matthieu Pesnot-Pin",
|
|
40
40
|
"license": "ISC",
|