feat(rcon): add admin server console
CI / validate (push) Successful in 6m5s
Release / release (push) Successful in 9m56s

This commit is contained in:
dmg
2026-08-07 21:44:00 -04:00
parent e43db34402
commit f9ccfd821d
26 changed files with 2800 additions and 4 deletions
+57
View File
@@ -0,0 +1,57 @@
import { describe, expect, it } from "vitest";
import { sanitizeRconOutput, validateRconCommand, validateRconConnection } from "./rcon-validation";
const allowed = "season4.somc.svc.cluster.local:25575,creative.somc.svc.cluster.local:25576";
describe("RCON validation", () => {
it("normalizes an allowlisted internal endpoint", () => {
expect(validateRconConnection({
name: " Season 4 ",
host: "SEASON4.SOMC.SVC.CLUSTER.LOCAL",
port: "25575",
password: "correct horse battery staple",
}, { allowedEndpoints: allowed, passwordRequired: true })).toEqual({
name: "Season 4",
host: "season4.somc.svc.cluster.local",
port: 25575,
password: "correct horse battery staple",
});
});
it("rejects unlisted hosts, ports, IP literals, and suffix confusion", () => {
for (const [host, port] of [
["postgres.somc.svc.cluster.local", "5432"],
["season4.somc.svc.cluster.local", "5432"],
["season4.somc.svc.cluster.local.attacker.example", "25575"],
["10.0.0.1", "25575"],
]) {
expect(validateRconConnection({ name: "Server", host, port, password: "secret" }, {
allowedEndpoints: allowed,
passwordRequired: true,
})).toBeNull();
}
});
it("allows a blank replacement password only while editing", () => {
expect(validateRconConnection({ name: "Server", host: "season4.somc.svc.cluster.local", port: "25575", password: "" }, {
allowedEndpoints: allowed,
passwordRequired: false,
})?.password).toBeNull();
expect(validateRconConnection({ name: "Server", host: "season4.somc.svc.cluster.local", port: "25575", password: "" }, {
allowedEndpoints: allowed,
passwordRequired: true,
})).toBeNull();
});
it("bounds commands by UTF-8 bytes and rejects control characters", () => {
expect(validateRconCommand(" list ")).toBe("list");
expect(validateRconCommand("say first\nsay second")).toBeNull();
expect(validateRconCommand("say \u001b[31mred")).toBeNull();
expect(validateRconCommand(`say ${"😀".repeat(300)}`)).toBeNull();
});
it("strips output controls and bounds output by UTF-8 bytes", () => {
expect(sanitizeRconOutput("ok\u001b[31mred\u0000done")).toBe("ok[31mreddone");
expect(Buffer.byteLength(sanitizeRconOutput("😀".repeat(20_000)), "utf8")).toBeLessThanOrEqual(65_536);
});
});