diff --git a/packages/host/src/Instance.ts b/packages/host/src/Instance.ts index 696d1da8..d8c9311c 100644 --- a/packages/host/src/Instance.ts +++ b/packages/host/src/Instance.ts @@ -15,6 +15,15 @@ import { exportData } from "./export.js"; import type Host from "./Host.js"; import { BaseInstancePlugin, InstanceHooks } from "./BaseInstancePlugin.js"; +// Reject save names that would escape the instance's saves directory. +function checkRequestSaveName(name: string) { + try { + lib.checkFilename(name); + } catch (err: any) { + throw new lib.RequestError(`Save name ${err.message}`); + } +} + const scriptCommands = [ "/cheat", "/editor", "/command", "/c", @@ -1268,6 +1277,9 @@ end`.replace(/\r?\n/g, " "); async handleInstanceStartRequest(request: lib.InstanceStartRequest) { let saveName = request.save; + if (saveName !== undefined) { + checkRequestSaveName(saveName); + } try { try { await this.prepare(); @@ -1327,6 +1339,7 @@ end`.replace(/\r?\n/g, " "); } async handleInstanceCreateSaveRequest(request: lib.InstanceCreateSaveRequest) { + checkRequestSaveName(request.name); this.notifyStatus("creating_save"); try { this.logger.verbose("Writing server-settings.json"); diff --git a/test/host/Instance.js b/test/host/Instance.js index 81511911..f396c105 100644 --- a/test/host/Instance.js +++ b/test/host/Instance.js @@ -223,6 +223,23 @@ describe("class Instance", function() { }); }); + describe("save name checks", function() { + it("should reject a start save outside the saves directory", async function() { + await assert.rejects( + instance.handleInstanceStartRequest(new lib.InstanceStartRequest("../escape.zip")), + lib.RequestError, + ); + }); + it("should reject a created save outside the saves directory", async function() { + await assert.rejects( + instance.handleInstanceCreateSaveRequest( + new lib.InstanceCreateSaveRequest("../escape.zip"), + ), + lib.RequestError, + ); + }); + }); + describe("._recordPlayerJoin()", function() { it("should add player to playersOnline", function() { instance._recordPlayerJoin("player");