From 2b9150bce293c6332950368c90e3d5dc3bf88663 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 5 Aug 2026 16:33:44 -0700 Subject: [PATCH] Chore: add proxmox param validation --- .../api/proxmox/stats/[...service].test.js | 27 +++++++++++++++++++ src/pages/api/proxmox/stats/[...service].js | 23 +++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/__tests__/pages/api/proxmox/stats/[...service].test.js b/src/__tests__/pages/api/proxmox/stats/[...service].test.js index b3651b96b..9c15229cb 100644 --- a/src/__tests__/pages/api/proxmox/stats/[...service].test.js +++ b/src/__tests__/pages/api/proxmox/stats/[...service].test.js @@ -37,6 +37,33 @@ describe("pages/api/proxmox/stats/[...service]", () => { expect(res.body).toEqual({ error: "Proxmox node parameter is required" }); }); + it.each([ + ["type", { service: ["pve", "100"], type: "../../cluster/resources#" }, "Invalid Proxmox type parameter"], + ["node", { service: ["../pve", "100"], type: "qemu" }, "Invalid Proxmox node parameter"], + ["VMID", { service: ["pve", "../../../cluster/resources#"], type: "qemu" }, "Invalid Proxmox VMID parameter"], + ])("rejects an invalid %s path parameter", async (_parameter, query, error) => { + const req = { query }; + const res = createMockRes(); + + await handler(req, res); + + expect(res.statusCode).toBe(400); + expect(res.body).toEqual({ error }); + expect(getProxmoxConfig).not.toHaveBeenCalled(); + expect(httpProxy).not.toHaveBeenCalled(); + }); + + it("rejects an array-valued type parameter", async () => { + const req = { query: { service: ["pve", "100"], type: ["qemu", "../../cluster/resources#"] } }; + const res = createMockRes(); + + await handler(req, res); + + expect(res.statusCode).toBe(400); + expect(res.body).toEqual({ error: "Invalid Proxmox type parameter" }); + expect(httpProxy).not.toHaveBeenCalled(); + }); + it("returns 500 when proxmox config is missing", async () => { getProxmoxConfig.mockReturnValue(null); diff --git a/src/pages/api/proxmox/stats/[...service].js b/src/pages/api/proxmox/stats/[...service].js index a053b5856..fefd4fe44 100644 --- a/src/pages/api/proxmox/stats/[...service].js +++ b/src/pages/api/proxmox/stats/[...service].js @@ -3,11 +3,14 @@ import createLogger from "utils/logger"; import { httpProxy } from "utils/proxy/http"; const logger = createLogger("proxmoxStatsService"); +const VALID_VM_TYPES = new Set(["qemu", "lxc"]); +const VALID_NODE = /^[A-Za-z0-9._-]+$/; +const VALID_VMID = /^\d+$/; export default async function handler(req, res) { const { service, type: vmType } = req.query; - const [node, vmid] = service; + const [node, vmid] = service || []; if (!node) { return res.status(400).send({ @@ -15,6 +18,24 @@ export default async function handler(req, res) { }); } + if (typeof node !== "string" || !VALID_NODE.test(node) || node.includes("..")) { + return res.status(400).send({ + error: "Invalid Proxmox node parameter", + }); + } + + if (typeof vmid !== "string" || !VALID_VMID.test(vmid)) { + return res.status(400).send({ + error: "Invalid Proxmox VMID parameter", + }); + } + + if (typeof vmType !== "string" || !VALID_VM_TYPES.has(vmType)) { + return res.status(400).send({ + error: "Invalid Proxmox type parameter", + }); + } + try { const proxmoxConfig = getProxmoxConfig();