test: add /approve gateway scope coverage (#1) (thanks @mitsuhiko)

This commit is contained in:
Peter Steinberger 2026-02-03 15:55:21 -08:00
parent efe2a464af
commit d41acf99a6
2 changed files with 49 additions and 0 deletions

View File

@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
### Fixes
- Security: require operator.approvals for gateway /approve commands. (#1) Thanks @mitsuhiko, @yueyueL.
- Security: Matrix allowlists now require full MXIDs; ambiguous name resolution no longer grants access. Thanks @MegaManSec.
- Security: enforce access-group gating for Slack slash commands when channel type lookup fails.
- Security: require validated shared-secret auth before skipping device identity on gateway connect.

View File

@ -98,4 +98,52 @@ describe("/approve command", () => {
expect(result.reply?.text).toContain("requires operator.approvals");
expect(mockCallGateway).not.toHaveBeenCalled();
});
it("allows gateway clients with approvals scope", async () => {
const cfg = {
commands: { text: true },
} as OpenClawConfig;
const params = buildParams("/approve abc allow-once", cfg, {
Provider: "webchat",
Surface: "webchat",
GatewayClientScopes: ["operator.approvals"],
});
const mockCallGateway = vi.mocked(callGateway);
mockCallGateway.mockResolvedValueOnce({ ok: true });
const result = await handleCommands(params);
expect(result.shouldContinue).toBe(false);
expect(result.reply?.text).toContain("Exec approval allow-once submitted");
expect(mockCallGateway).toHaveBeenCalledWith(
expect.objectContaining({
method: "exec.approval.resolve",
params: { id: "abc", decision: "allow-once" },
}),
);
});
it("allows gateway clients with admin scope", async () => {
const cfg = {
commands: { text: true },
} as OpenClawConfig;
const params = buildParams("/approve abc allow-once", cfg, {
Provider: "webchat",
Surface: "webchat",
GatewayClientScopes: ["operator.admin"],
});
const mockCallGateway = vi.mocked(callGateway);
mockCallGateway.mockResolvedValueOnce({ ok: true });
const result = await handleCommands(params);
expect(result.shouldContinue).toBe(false);
expect(result.reply?.text).toContain("Exec approval allow-once submitted");
expect(mockCallGateway).toHaveBeenCalledWith(
expect.objectContaining({
method: "exec.approval.resolve",
params: { id: "abc", decision: "allow-once" },
}),
);
});
});