mirror of
https://github.com/penpot/penpot.git
synced 2026-05-13 12:04:06 +00:00
🐛 Bind MCP ReplServer to localhost to prevent unauthenticated RCE
The ReplServer Express app was calling `app.listen(port)` with no host argument, causing Node/Express to default to binding on all interfaces (0.0.0.0). Combined with the unauthenticated /execute endpoint, any network peer could POST arbitrary JS and get it run inside the MCP process. Fix: add a `host` parameter (default "localhost") to the ReplServer constructor and pass it to `app.listen`. The call site in PenpotMcpServer now forwards `this.host` (sourced from PENPOT_MCP_SERVER_HOST env var, default "localhost"), so environment- variable overrides continue to work. Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
697a825d76
commit
798ee46b4a
@ -11,6 +11,7 @@
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
- Fix MCP ReplServer binding to all interfaces (0.0.0.0) instead of localhost, allowing unauthenticated RCE
|
||||
- Fix incorrect invitation token handling on register process [Github #9380](https://github.com/penpot/penpot/pull/9380)
|
||||
- Fix incorrect handling of version restore operation [Github #9041](https://github.com/penpot/penpot/pull/9041)
|
||||
- Fix false “text editing” warning when applying tokens [Github #6346](https://github.com/penpot/penpot/issues/9346)
|
||||
|
||||
@ -92,7 +92,7 @@ export class PenpotMcpServer {
|
||||
this.tools = this.initTools();
|
||||
|
||||
this.pluginBridge = new PluginBridge(this, this.webSocketPort);
|
||||
this.replServer = new ReplServer(this.pluginBridge, this.replPort);
|
||||
this.replServer = new ReplServer(this.pluginBridge, this.replPort, this.host);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,13 +17,16 @@ export class ReplServer {
|
||||
private readonly logger = createLogger("ReplServer");
|
||||
private readonly app: express.Application;
|
||||
private readonly port: number;
|
||||
private readonly host: string;
|
||||
private server: any;
|
||||
|
||||
constructor(
|
||||
private readonly pluginBridge: PluginBridge,
|
||||
port: number = 4403
|
||||
port: number = 4403,
|
||||
host: string = "localhost"
|
||||
) {
|
||||
this.port = port;
|
||||
this.host = host;
|
||||
this.app = express();
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
@ -86,9 +89,9 @@ export class ReplServer {
|
||||
*/
|
||||
public async start(): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
this.server = this.app.listen(this.port, () => {
|
||||
this.server = this.app.listen(this.port, this.host, () => {
|
||||
this.logger.info(`REPL server started on port ${this.port}`);
|
||||
this.logger.info(`REPL interface URL: http://${this.pluginBridge.mcpServer.host}:${this.port}`);
|
||||
this.logger.info(`REPL interface URL: http://${this.host}:${this.port}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user