From f2bd963466ef2a8ad5604901c306bf11dbd5b53e Mon Sep 17 00:00:00 2001 From: underwaterresearch Date: Sat, 4 Apr 2026 09:40:49 +0000 Subject: [PATCH] fix: block stale gateway urls for stopped agents --- backend-api/__tests__/agents.test.js | 18 ++++++++++++++++++ backend-api/routes/agents.js | 5 ++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/backend-api/__tests__/agents.test.js b/backend-api/__tests__/agents.test.js index 930a5cc..7e3241c 100644 --- a/backend-api/__tests__/agents.test.js +++ b/backend-api/__tests__/agents.test.js @@ -199,6 +199,7 @@ describe("GET /agents/:id/gateway-url", () => { gateway_token: "gateway-token", gateway_host_port: 19123, user_id: "user-1", + status: "running", }], }); @@ -212,6 +213,23 @@ describe("GET /agents/:id/gateway-url", () => { delete process.env.GATEWAY_HOST; }); + + it("rejects gateway url lookups for stopped agents so stale ports are not exposed", async () => { + mockDb.query.mockResolvedValueOnce({ + rows: [{ + id: "a-stopped-gateway", + container_id: "container-gateway", + gateway_host_port: 19123, + user_id: "user-1", + status: "stopped", + }], + }); + + const res = await auth(request(app).get("/agents/a-stopped-gateway/gateway-url")); + + expect(res.status).toBe(409); + expect(res.body.error).toMatch(/only available while running/i); + }); }); describe("POST /agents/deploy", () => { diff --git a/backend-api/routes/agents.js b/backend-api/routes/agents.js index c128752..255ed1e 100644 --- a/backend-api/routes/agents.js +++ b/backend-api/routes/agents.js @@ -88,11 +88,14 @@ function parseInterval(pg) { // Get the gateway control UI URL (published host port for direct browser access) router.get("/:id/gateway-url", asyncHandler(async (req, res) => { const result = await db.query( - "SELECT id, container_id, gateway_token, gateway_host_port, user_id FROM agents WHERE id = $1 AND user_id = $2", + "SELECT id, container_id, gateway_token, gateway_host_port, user_id, status FROM agents WHERE id = $1 AND user_id = $2", [req.params.id, req.user.id] ); const agent = result.rows[0]; if (!agent) return res.status(404).json({ error: "Agent not found" }); + if (!["running", "warning"].includes(agent.status)) { + return res.status(409).json({ error: "Agent gateway is only available while running" }); + } if (!agent.container_id) return res.status(409).json({ error: "No container" }); // Use stored host port if available, otherwise fall back to Docker inspect