Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
39f8b77
fix(policy): restrict Hermes Discord binary access
prekshivyas Aug 31, 2026
69630ff
test(policy): cover Discord runtime guidance
prekshivyas Aug 31, 2026
7bd41ca
chore(policy): refresh reviewed runtime bundle
prekshivyas Aug 31, 2026
6b3c817
merge: refresh Hermes Discord fix from main
prekshivyas Aug 31, 2026
f03fdec
merge: refresh Hermes Discord fix from main
prekshivyas Aug 31, 2026
154699d
Merge branch 'main' into codex/fix-hermes-discord-node-policy
cv Sep 1, 2026
86f89a8
Merge branch 'main' into codex/fix-hermes-discord-node-policy
prekshivyas Sep 1, 2026
2bd37f0
fix(policy): validate Hermes Discord with Python
prekshivyas Sep 1, 2026
7961bc8
fix(policy): complete Hermes Discord regression evidence
prekshivyas Sep 1, 2026
9ba480c
test(e2e): cover Hermes Discord REST proof
prekshivyas Sep 1, 2026
b8813ca
merge: sync upstream main
prekshivyas Sep 1, 2026
74b0e67
merge: sync upstream main
prekshivyas Sep 1, 2026
e51270f
test(e2e): prove Hermes Discord REST rewrite
cv Sep 1, 2026
7b174c4
test(e2e): prove Hermes denies Node Discord egress
cv Sep 1, 2026
19e3815
refactor(policy): keep Discord guidance local
cv Sep 1, 2026
98baa26
test(e2e): tighten Hermes Discord denial proof
cv Sep 1, 2026
eb102f5
refactor(policy): restore manifest-owned guidance
cv Sep 1, 2026
928df08
fix(build): refresh reviewed startup runtime bundle
cv Sep 1, 2026
e34b1e0
merge: resolve conflicts with main
github-actions[bot] Sep 1, 2026
e59ea72
fix(policy): document Hermes Discord remediation
prekshivyas Sep 1, 2026
e25b802
Merge remote-tracking branch 'origin/main' into HEAD
prekshivyas Sep 1, 2026
1e6b8c0
Merge remote-tracking branch 'origin/main' into codex/pr10682-final
prekshivyas Sep 1, 2026
e12caf5
merge: resolve conflicts with main
github-actions[bot] Sep 1, 2026
4b621c8
merge(e2e): resolve Hermes Discord fixture conflicts
prekshivyas Sep 1, 2026
b4981ce
merge(main): synchronize PR 10682
prekshivyas Sep 1, 2026
2228126
Merge branch 'main' into codex/fix-hermes-discord-node-policy
prekshivyas Sep 1, 2026
67b53ed
merge(pr): preserve remote PR updates
prekshivyas Sep 1, 2026
1b2a896
merge(main): synchronize PR 10682
prekshivyas Sep 1, 2026
531642e
merge(main): synchronize PR 10682
prekshivyas Sep 1, 2026
864e37d
Merge branch 'main' into codex/fix-hermes-discord-node-policy
prekshivyas Sep 1, 2026
b3fd418
test(e2e): preserve Hermes denial evidence
prekshivyas Sep 1, 2026
e84a83f
merge(main): refresh PR 10682
prekshivyas Sep 1, 2026
db2377f
test(e2e): map Hermes denial probe parity
prekshivyas Sep 1, 2026
ebdcc63
merge(main): refresh PR 10682
prekshivyas Sep 1, 2026
dd7b229
test(e2e): remove redundant Hermes policy read
prekshivyas Sep 2, 2026
388e0fb
Merge remote-tracking branch 'origin/main' into codex/pr10682-e2e-den…
prekshivyas Sep 2, 2026
21a97b0
merge: resolve conflicts with main
github-actions[bot] Sep 2, 2026
df1f627
merge: refresh from upstream main
prekshivyas Sep 2, 2026
c9199a0
fix(ci): refresh reviewed startup runtime
prekshivyas Sep 2, 2026
7cfd627
fix(policy): accept Discord HTTP reachability evidence
prekshivyas Sep 2, 2026
3985a1d
merge: resolve conflicts with main
github-actions[bot] Sep 2, 2026
d858d2c
fix(discord): align Hermes review guidance
prekshivyas Sep 2, 2026
087024c
fix(test): drop retired Hermes Node probe
prekshivyas Sep 2, 2026
106f727
fix(discord): restrict Hermes runtime authority
prekshivyas Sep 2, 2026
9e79653
docs(policy): align Hermes Discord remediation
prekshivyas Sep 2, 2026
05bca26
fix(policy): complete Hermes Discord authority proof
prekshivyas Sep 2, 2026
2b7ede2
test(policy): align Hermes Discord CI coverage
prekshivyas Sep 2, 2026
260cf29
merge: resolve conflicts with main
github-actions[bot] Sep 2, 2026
1d0fb71
test(policy): consolidate Discord reconciliation
prekshivyas Sep 2, 2026
46127b3
test(e2e): share fake messaging policy setup
prekshivyas Sep 2, 2026
eb36cf7
test(e2e): cover explicit fake policy binaries
prekshivyas Sep 2, 2026
5e6bf13
test(e2e): move fake policy parity proof
prekshivyas Sep 2, 2026
1503226
test(e2e): keep parity proof behavior-focused
prekshivyas Sep 2, 2026
2e3e64c
Merge branch 'main' into codex/fix-hermes-discord-node-policy
prekshivyas Sep 2, 2026
5a84c21
merge(main): resolve conflicts for #10682
prekshivyas Sep 3, 2026
355b7ea
fix(pi): refresh Discord qualification receipts
prekshivyas Sep 3, 2026
f4249cd
fix(policy): restore Hermes Discord trust proofs
prekshivyas Sep 3, 2026
e46edd4
fix(security): refresh Pi receipts and harden fixture
prekshivyas Sep 3, 2026
d29047c
test(e2e): require attached fixture providers
prekshivyas Sep 3, 2026
178c820
test(e2e): record Slack credential phase
prekshivyas Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/lib/actions/sandbox/policy-channel-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,8 @@ describe("addSandboxPolicy", () => {
await addSandboxPolicy("test-sandbox", { preset: "discord", yes: true });

expect(printedText()).toContain("curl is not in the preset binary allowlist");
expect(printedText()).toContain("Node HTTPS");
expect(printedText()).toContain("configured agent runtime");
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
expect(printedText()).not.toContain("Node HTTPS");
expect(promptMock).not.toHaveBeenCalled();
expect(applyPresetMock).toHaveBeenCalledWith("test-sandbox", "discord", {
suppressDisclosure: true,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/messaging/channels/discord/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export const discordManifest = {
validationWarningLines: [
"For Discord preset validation, do not use curl as the success signal:",
"curl is not in the preset binary allowlist, so curl probes can fail even",
"when the policy is working. Use Node HTTPS against",
"when the policy is working. Use the configured agent runtime against",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1][Operability/documentation] configured agent runtime is not an actionable validation contract for the two supported agents, and docs/reference/troubleshooting.mdx:2344-2384 still says the preset allows Node and prescribes Node-only probes. Impact: Hermes users will run a binary this PR correctly denies, misdiagnose healthy fail-closed behavior, and may widen the policy to compensate. Smallest safe fix: provide explicit agent-specific validation commands or named procedures with expected success/failure interpretation, and update troubleshooting to distinguish OpenClaw Node from Hermes Python. Regression: assert the emitted warning selects a concrete supported procedure for each agent and that superseded generic Node guidance is absent for Hermes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 2bd37f0. Discord validation metadata now owns separate OpenClaw Node and Hermes venv-Python procedures; policy add selects the procedure from the sandbox agent; CLI/runtime regressions prove each agent receives only its supported command; and troubleshooting now has separate OpenClaw and Hermes sections with success/failure interpretation. The full npm run docs build and npm run validate:pr pass.

"https://discord.com/api/v10/gateway or validate the configured",
'messaging bridge/gateway path. DNS-only checks such as dns.resolve("gateway.discord.gg")',
"can also be inconclusive behind a proxy.",
Expand Down
1 change: 0 additions & 1 deletion src/lib/messaging/channels/discord/policy/hermes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,5 @@ network_policies:
rules:
- allow: { method: GET, path: "/**" }
binaries:
- { path: /usr/local/bin/node }
- { path: /usr/bin/python3* }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1][Security testing] The shipped Hermes Discord policy is Python-only here, but test/e2e/live/hermes-discord.test.ts:145-164 rebuilds its fake policy with /usr/local/bin/node and /usr/bin/node, then :686-716 performs the REST proof through sandboxNode. Impact: the live gate validates a wider authority than production and can stay green while the least-privilege contract is broken or unexercised. Smallest safe fix: remove both Node grants from the fake policy and replace the REST probe with /opt/hermes/.venv/bin/python (or the reviewed Hermes Python helper), preserving the placeholder, credential-binding, inspected REST/WebSocket, timeout, and token-isolation assertions. Regression: make the lane fail if Node is reintroduced or if the Python runtime cannot reach the credential-bound Discord route.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 2bd37f0. The Hermes fake Discord policy no longer grants either Node binary. The WebSocket and credential-bound REST proofs both run through /opt/hermes/.venv/bin/python, and the live lane reads the effective policy and fails if Node appears in either the production or fake Discord policy. Focused policy/onboarding tests (125), Hermes E2E-support tests (4), CLI type-check, docs, and npm run validate:pr pass. Fresh exact-head hermes-discord E2E will be dispatched after normal candidate checks and reviews stabilize.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Migrate the durable live policy, not only the preset source. Impact: existing Hermes Discord sandboxes retain the old /usr/local/bin/node grant across upgrade/rebuild because rebuild preserves the captured OpenShell policy; fresh-onboard tests cannot prove this security fix reaches deployed sandboxes. Smallest safe fix: reconcile the discord preset on a supported lifecycle path, or emit a named per-sandbox remediation that reapplies the preset and verifies Node is absent. Regression: start from a persisted prior Discord policy containing Node, run the supported upgrade/rebuild/remediation, and prove Node is removed while the Python binaries and credential binding remain exactly once.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed on exact head 1e6b8c07d78f74106cd5968797df6175b7815b6e by e59ea726fc0d5ea22ac04066096a91dfaca8e502. The Hermes-only policy documentation now names the supported per-sandbox remediation: preview and reapply the maintained discord preset, then inspect the live policy. The new test/runtime/policy/hermes-discord-policy-reconciliation.test.ts regression registers a configured Hermes Discord sandbox, persists the prior live policy with /usr/local/bin/node, invokes the supported applyPreset(..., "discord") path, and proves the resulting binary list is exactly /usr/bin/python3* plus /opt/hermes/.venv/bin/python. It also proves the discord.com credential-bound endpoint remains exactly once with provider hermes-sandbox-discord-bridge. npm run validate:pr passes on this exact head based on canonical main f68ccab0c9cde2afbef32425fea1f2472a0f8532; the focused extraction plus policy and growth coverage passes 142 tests, the docs build passes, and the reviewed runtime bundle deterministically regenerates.

- { path: /opt/hermes/.venv/bin/python }
2 changes: 1 addition & 1 deletion test/mcp/mcp-tool-discovery-image-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ describe("MCP tool discovery image contract", () => {
// source-shape-contract: security -- Exact reviewed runtime digests reject substituted executable and license artifacts before managed image construction.
it.each([
{
expectedHash: "d77b6d5465f651bf60eed9d978de14e72ebb0db35bb5a691c3eab84d554e3f9a",
expectedHash: "96068e04b3fb8c325a2532a4a108c92200199367a2b6fc712cdb0d122d7a06b9",
relativePath: "managed-startup-image-runtime.bundle",
},
{
Expand Down
10 changes: 10 additions & 0 deletions test/onboarding/effective-policy-contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,16 @@ describe("effective built-in policy contracts", () => {
});
});

it("denies Node.js egress in the Hermes Discord preset (#10655)", () => {
const effective = composePresets(["discord"], "hermes");
const discord = requireNetworkPolicy(effective, "discord");

expect(binaries(discord)).toEqual([
"/opt/hermes/.venv/bin/python",
"/usr/bin/python3*",
]);
});

it("composes Hermes-specific messaging mutation and runtime identity rules", () => {
const effective = composePresets(["discord", "slack", "wechat"], "hermes");
const discord = requireNetworkPolicy(effective, "discord");
Expand Down
5 changes: 3 additions & 2 deletions test/runtime/policy/policies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,13 @@ describe("policies", () => {
expect(policies.getPresetValidationWarning("wechat")).toContain("WeChat");
});

it("adds Discord validation guidance for Node probes instead of curl or DNS-only checks", () => {
it("adds Discord validation guidance for agent runtime probes instead of curl or DNS-only checks", () => {
const warning = policies.getPresetValidationWarning("discord");

expect(warning).toContain("curl");
expect(warning).toContain("preset binary allowlist");
expect(warning).toContain("Node HTTPS");
expect(warning).toContain("configured agent runtime");
expect(warning).not.toContain("Node HTTPS");
expect(warning).toContain("https://discord.com/api/v10/gateway");
expect(warning).toContain('dns.resolve("gateway.discord.gg")');
});
Expand Down

Large diffs are not rendered by default.

Loading