














@@ -17,6 +17,33 @@ describe("parseExecApprovalResultText", () => {
1717});
1818});
191920+it("parses denied results with nested parentheses in metadata", () => {
21+const input =
22+"Exec denied (gateway id=req-1, approval-timeout (allowlist-miss)): source ~/.zprofile && kubectl get pods";
23+24+expect(parseExecApprovalResultText(input)).toEqual({
25+kind: "denied",
26+raw: input,
27+metadata: "gateway id=req-1, approval-timeout (allowlist-miss)",
28+body: "source ~/.zprofile && kubectl get pods",
29+});
30+});
31+32+it("parses denied results with the canonical colon-separated deniedReason", () => {
33+// Producer (src/agents/bash-tools.exec-host-gateway.ts) emits a colon
34+// separator instead of nested parens to keep the (...)-delimited wire
35+// format unambiguous. This is the format real timeouts now produce.
36+const input =
37+"Exec denied (gateway id=req-1, approval-timeout: allowlist-miss): source ~/.zprofile && kubectl get pods";
38+39+expect(parseExecApprovalResultText(input)).toEqual({
40+kind: "denied",
41+raw: input,
42+metadata: "gateway id=req-1, approval-timeout: allowlist-miss",
43+body: "source ~/.zprofile && kubectl get pods",
44+});
45+});
46+2047it("parses finished results", () => {
2148expect(
2249parseExecApprovalResultText("Exec finished (gateway id=req-1, code 0)\nall good"),
@@ -28,6 +55,17 @@ describe("parseExecApprovalResultText", () => {
2855});
2956});
305758+it("parses finished results with nested parentheses in metadata", () => {
59+const input = "Exec finished (gateway id=req-1, note (nested), code 0)\nall good";
60+61+expect(parseExecApprovalResultText(input)).toEqual({
62+kind: "finished",
63+raw: input,
64+metadata: "gateway id=req-1, note (nested), code 0",
65+body: "all good",
66+});
67+});
68+3169it("parses completed results", () => {
3270expect(parseExecApprovalResultText("Exec completed: done")).toEqual({
3371kind: "completed",
@@ -42,12 +80,31 @@ describe("parseExecApprovalResultText", () => {
4280raw: "some random text",
4381});
4482});
83+84+it.each([
85+"Exec denied (anything): bar",
86+"Exec denied (just-text): foo",
87+"Exec denied (request-id=abc, denied): cmd",
88+"Exec denied (id=req-1, user-denied): cmd",
89+"Exec finished (anything)\nbody",
90+"Exec finished (status: ok)\nbody",
91+])(
92+"returns other when metadata is not gateway/node sourced (CWE-841 spoof guard): %s",
93+(input) => {
94+expect(parseExecApprovalResultText(input)).toEqual({
95+kind: "other",
96+raw: input,
97+});
98+},
99+);
45100});
4610147102describe("isExecDeniedResultText", () => {
48103it.each([
49104"Exec denied (gateway id=req-1, approval-timeout): uname -a",
50105"exec denied (gateway id=req-1, approval-timeout): uname -a",
106+"Exec denied (gateway id=req-1, approval-timeout (allowlist-miss)): uname -a",
107+"Exec denied (gateway id=req-1, approval-timeout: allowlist-miss): uname -a",
51108])("matches denied payloads: %s", (input) => {
52109expect(isExecDeniedResultText(input)).toBe(true);
53110});
@@ -63,6 +120,14 @@ describe("formatExecDeniedUserMessage", () => {
63120"Exec denied (gateway id=req-1, approval-timeout): uname -a",
64121"Command did not run: approval timed out.",
65122],
123+[
124+"Exec denied (gateway id=req-1, approval-timeout (allowlist-miss)): uname -a",
125+"Command did not run: approval timed out.",
126+],
127+[
128+"Exec denied (gateway id=req-1, approval-timeout: allowlist-miss): uname -a",
129+"Command did not run: approval timed out.",
130+],
66131[
67132"Exec denied (gateway id=req-1, user-denied): uname -a",
68133"Command did not run: approval was denied.",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。