fix: bound restart handoff ttl

This commit is contained in:
Shakker
2026-05-05 06:51:12 +01:00
parent acb0acd8dd
commit 4a24b6dbc4
2 changed files with 31 additions and 0 deletions

View File

@@ -190,6 +190,36 @@ describe("gateway restart handoff", () => {
expect(fs.existsSync(handoffPath(env))).toBe(false);
});
it("rejects persisted handoffs with a ttl longer than the supported window", () => {
const env = createHandoffEnv();
fs.writeFileSync(
handoffPath(env),
`${JSON.stringify({
kind: GATEWAY_SUPERVISOR_RESTART_HANDOFF_KIND,
version: 1,
intentId: "too-long",
pid: 111,
createdAt: 1_000,
expiresAt: 61_001,
source: "plugin-change",
restartKind: "full-process",
supervisorMode: "external",
})}\n`,
{ encoding: "utf8", mode: 0o600 },
);
expect(readGatewayRestartHandoffSync(env, 1_001)).toBeNull();
expect(
consumeGatewayRestartHandoffForExitedProcessSync({
env,
exitedPid: 111,
now: 1_001,
}),
).toBeNull();
expect(fs.existsSync(handoffPath(env))).toBe(false);
});
it("does not follow an existing handoff-path symlink when writing", () => {
const env = createHandoffEnv();
const targetPath = path.join(env.OPENCLAW_STATE_DIR ?? "", "attacker-target.txt");

View File

@@ -157,6 +157,7 @@ function parseGatewayRestartHandoff(raw: string): GatewayRestartHandoff | null {
typeof parsed.expiresAt !== "number" ||
!Number.isFinite(parsed.expiresAt) ||
parsed.expiresAt <= parsed.createdAt ||
parsed.expiresAt - parsed.createdAt > GATEWAY_RESTART_HANDOFF_TTL_MS ||
!isSource(parsed.source) ||
!isRestartKind(parsed.restartKind) ||
!isSupervisorMode(parsed.supervisorMode)