From 1857a6a2c575b30814668308f3c1570bc8593bdf Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 20 Apr 2026 18:28:00 -0700 Subject: [PATCH 1/3] fix(policy): add tls: terminate to telegram preset endpoint The telegram.yaml preset was missing tls: terminate on the api.telegram.org endpoint. The baseline openclaw-sandbox.yaml has it, but the preset omitted it. After PR #2098 changed how the gateway handles the tls field, the omission causes the L7 proxy to return 403 for live policy-add requests (TC-NET-03). --- nemoclaw-blueprint/policies/presets/telegram.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/nemoclaw-blueprint/policies/presets/telegram.yaml b/nemoclaw-blueprint/policies/presets/telegram.yaml index 55a2fdfb0e3..2a9e1167931 100644 --- a/nemoclaw-blueprint/policies/presets/telegram.yaml +++ b/nemoclaw-blueprint/policies/presets/telegram.yaml @@ -12,6 +12,7 @@ network_policies: - host: api.telegram.org port: 443 protocol: rest + tls: terminate enforcement: enforce rules: - allow: { method: GET, path: "/bot*/**" } From c4164b0b4eebd54ac44318f26bce61b65d695140 Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 20 Apr 2026 18:35:31 -0700 Subject: [PATCH 2/3] test(policy): update tls assertion for telegram REST preset The original test asserted all messaging presets must not contain tls: terminate. After OpenShell v0.0.15 changed TLS auto-termination behavior, REST-only presets like telegram need tls: terminate for the L7 proxy to work. Discord and Slack use tls: skip on their WebSocket endpoints only. Split the assertion: WebSocket presets (discord, slack) must not use terminate; the telegram REST preset must use it. --- test/policies.test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/policies.test.ts b/test/policies.test.ts index f95ae34f1ef..5635e920628 100644 --- a/test/policies.test.ts +++ b/test/policies.test.ts @@ -606,14 +606,20 @@ describe("policies", () => { } }); - it("messaging REST presets do not pin deprecated tls termination", () => { - for (const name of ["discord", "slack", "telegram"]) { + it("messaging WebSocket presets use tls: skip, not terminate", () => { + for (const name of ["discord", "slack"]) { const content = policies.loadPreset(name); expect(content).toBeTruthy(); expect(content.includes("tls: terminate")).toBe(false); } }); + it("telegram REST preset uses tls: terminate for L7 proxy", () => { + const content = policies.loadPreset("telegram"); + expect(content).toBeTruthy(); + expect(content.includes("tls: terminate")).toBe(true); + }); + it("pypi preset allows HEAD for pip lazy-wheel metadata checks", () => { // pip and uv use HEAD requests for lazy wheel downloads and // range-request support. GET-only would break pip install. From f2210b0951fecb57254d27990e5f5d285375fddc Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 20 Apr 2026 18:43:18 -0700 Subject: [PATCH 3/3] test(policy): assert tls on specific endpoint blocks, not substrings Use regex patterns that match host + tls on the same endpoint block so regressions in one endpoint cannot be masked by a correct sibling. Addresses CodeRabbit review feedback. --- test/policies.test.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test/policies.test.ts b/test/policies.test.ts index 5635e920628..1f304f39757 100644 --- a/test/policies.test.ts +++ b/test/policies.test.ts @@ -606,18 +606,26 @@ describe("policies", () => { } }); - it("messaging WebSocket presets use tls: skip, not terminate", () => { - for (const name of ["discord", "slack"]) { - const content = policies.loadPreset(name); + it("messaging WebSocket presets keep tls: skip on gateway endpoints", () => { + const cases = [ + { preset: "discord", pattern: /host:\s*gateway\.discord\.gg[\s\S]*?tls:\s*skip/ }, + { preset: "slack", pattern: /host:\s*wss-primary\.slack\.com[\s\S]*?tls:\s*skip/ }, + { preset: "slack", pattern: /host:\s*wss-backup\.slack\.com[\s\S]*?tls:\s*skip/ }, + ]; + + for (const { preset, pattern } of cases) { + const content = policies.loadPreset(preset); expect(content).toBeTruthy(); - expect(content.includes("tls: terminate")).toBe(false); + expect(content).toMatch(pattern); } }); it("telegram REST preset uses tls: terminate for L7 proxy", () => { const content = policies.loadPreset("telegram"); expect(content).toBeTruthy(); - expect(content.includes("tls: terminate")).toBe(true); + expect(content).toMatch( + /host:\s*api\.telegram\.org[\s\S]*?protocol:\s*rest[\s\S]*?tls:\s*terminate/, + ); }); it("pypi preset allows HEAD for pip lazy-wheel metadata checks", () => {