fix(phone-control): reject invalid arm durations · openclaw/openclaw@e5063f5
steipete
·
2026-05-29
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -250,6 +250,25 @@ describe("phone-control plugin", () => {
|
250 | 250 | }); |
251 | 251 | }); |
252 | 252 | |
| 253 | +it("rejects invalid arm durations without mutating phone control", async () => { |
| 254 | +await withRegisteredPhoneControl(async ({ command, writeConfigFile }) => { |
| 255 | +const typoRes = await command.handler({ |
| 256 | + ...createCommandContext("arm writes forever"), |
| 257 | +channel: "webchat", |
| 258 | +gatewayClientScopes: ["operator.admin"], |
| 259 | +}); |
| 260 | +const overflowRes = await command.handler({ |
| 261 | + ...createCommandContext("arm writes 9007199254740993d"), |
| 262 | +channel: "webchat", |
| 263 | +gatewayClientScopes: ["operator.admin"], |
| 264 | +}); |
| 265 | + |
| 266 | +expect(typoRes?.text ?? "").toContain("Invalid duration"); |
| 267 | +expect(overflowRes?.text ?? "").toContain("Invalid duration"); |
| 268 | +expect(writeConfigFile).not.toHaveBeenCalled(); |
| 269 | +}); |
| 270 | +}); |
| 271 | + |
253 | 272 | it("allows external owner callers without gateway scopes to mutate phone control", async () => { |
254 | 273 | await withRegisteredPhoneControl(async ({ command, writeConfigFile }) => { |
255 | 274 | const res = await command.handler({ |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -75,7 +75,8 @@ function parseDurationMs(input: string | undefined): number | null {
|
75 | 75 | } |
76 | 76 | const unit = m[2]; |
77 | 77 | const mult = unit === "s" ? 1000 : unit === "m" ? 60_000 : unit === "h" ? 3_600_000 : 86_400_000; |
78 | | -return n * mult; |
| 78 | +const durationMs = n * mult; |
| 79 | +return Number.isSafeInteger(durationMs) ? durationMs : null; |
79 | 80 | } |
80 | 81 | |
81 | 82 | function formatDuration(ms: number): string { |
@@ -425,7 +426,10 @@ export default definePluginEntry({
|
425 | 426 | if (!group) { |
426 | 427 | return { text: `Usage: /phone arm <group> [duration]\nGroups: ${formatGroupList()}` }; |
427 | 428 | } |
428 | | -const durationMs = parseDurationMs(tokens[2]) ?? 10 * 60_000; |
| 429 | +const durationMs = tokens[2] === undefined ? 10 * 60_000 : parseDurationMs(tokens[2]); |
| 430 | +if (durationMs === null) { |
| 431 | +return { text: "Invalid duration. Use values like 30s, 10m, 2h, or 1d." }; |
| 432 | +} |
429 | 433 | const expiresAtMs = Date.now() + durationMs; |
430 | 434 | |
431 | 435 | const commands = resolveCommandsForGroup(group); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。