diff --git a/apps/Backend/src/routes/network-backup-public.ts b/apps/Backend/src/routes/network-backup-public.ts index 7e3065bf..0565fcb8 100644 --- a/apps/Backend/src/routes/network-backup-public.ts +++ b/apps/Backend/src/routes/network-backup-public.ts @@ -9,7 +9,27 @@ const router = Router(); const UPLOADS_DIR = path.resolve(process.cwd(), "uploads"); -function checkApiKey(req: Request, res: Response): boolean { +function isLanIp(ip: string): boolean { + return ( + /^127\./.test(ip) || + /^10\./.test(ip) || + /^192\.168\./.test(ip) || + /^172\.(1[6-9]|2\d|3[01])\./.test(ip) + ); +} + +function checkAccess(req: Request, res: Response): boolean { + // Only allow requests from the local network + const ip = + (req.headers["x-real-ip"] as string) || + (req.headers["x-forwarded-for"] as string)?.split(",")[0].trim() || + req.socket.remoteAddress || + ""; + if (!isLanIp(ip)) { + res.status(403).json({ error: "Access restricted to local network" }); + return false; + } + const providedKey = req.headers["x-network-backup-key"] as string | undefined; if (!providedKey) { res.status(401).json({ error: "Missing X-Network-Backup-Key header" }); @@ -25,7 +45,7 @@ function checkApiKey(req: Request, res: Response): boolean { // GET /api/database-management/network-backup router.get("/network-backup", async (req: Request, res: Response): Promise => { - if (!checkApiKey(req, res)) return; + if (!checkAccess(req, res)) return; const pg = spawn( "pg_dump", @@ -59,7 +79,7 @@ router.get("/network-backup", async (req: Request, res: Response): Promise // GET /api/database-management/network-backup-files router.get("/network-backup-files", (req: Request, res: Response): any => { - if (!checkApiKey(req, res)) return; + if (!checkAccess(req, res)) return; if (!fs.existsSync(UPLOADS_DIR)) { return res.status(200).end();