Skip to content

feat: add local exec-policy CLI#64050

Merged
Takhoffman merged 16 commits into
mainfrom
codex/exec-policy-cli
Apr 10, 2026
Merged

feat: add local exec-policy CLI#64050
Takhoffman merged 16 commits into
mainfrom
codex/exec-policy-cli

Conversation

@Takhoffman

Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: operators currently have to manage tools.exec.* and ~/.openclaw/exec-approvals.json separately, with mismatched CLI ergonomics (config set vs JSON-file replacement).
  • Why it matters: this makes it easy to think exec approvals are "off" when the effective merged policy is still stricter, and it hides the two-layer model behind different tools.
  • What changed: add a new local openclaw exec-policy CLI with show, preset, and set commands that synchronizes requested exec policy and host approvals together.
  • What did NOT change (scope boundary): this PR does not yet mutate remote gateway config or node-host approvals/config over RPC; the new command is intentionally local-first.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: N/A
  • Missing detection / guardrail: N/A
  • Contributing context (if known): N/A

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/cli/exec-policy-cli.test.ts, src/cli/program/register.subclis.test.ts
  • Scenario the test should lock in: exec-policy show reports the merged local policy, preset yolo updates both config and approvals, and set applies explicit synced values.
  • Why this is the smallest reliable guardrail: command behavior is local CLI orchestration over existing config/approvals helpers, so focused CLI tests are enough to lock the new surface.
  • Existing test that already covers this (if any): src/cli/program/register.subclis.test.ts
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

  • Adds openclaw exec-policy show to display config path, approvals path, and effective merged exec policy.
  • Adds openclaw exec-policy preset yolo|cautious|deny-all to synchronize local tools.exec.* and host approvals defaults together.
  • Adds openclaw exec-policy set --host/--security/--ask/--ask-fallback for explicit local synchronization without editing JSON.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[user wants no-prompt exec] -> [openclaw config set tools.exec.*] + [manually edit approvals JSON] -> [check effective merge separately]

After:
[user wants no-prompt exec] -> [openclaw exec-policy preset yolo] -> [config + host approvals updated together] -> [show effective merge]

Security Impact (required)

  • New permissions/capabilities? (Yes/No)
    • No
  • Secrets/tokens handling changed? (Yes/No)
    • No
  • New/changed network calls? (Yes/No)
    • No
  • Command/tool execution surface changed? (Yes/No)
    • Yes
  • Data access scope changed? (Yes/No)
    • No
  • If any Yes, explain risk + mitigation:
    • The new command changes local exec-policy configuration and local host approvals in one step. Risk is operator misuse of permissive presets such as yolo. Mitigation: scope is local-only, the command names/presets are explicit, and show exposes the effective merged result immediately after mutation.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local Node CLI
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): local tools.exec.* plus local ~/.openclaw/exec-approvals.json

Steps

  1. Run openclaw exec-policy show --json.
  2. Run openclaw exec-policy preset yolo --json.
  3. Run openclaw exec-policy set --host node --security full --ask off --ask-fallback allowlist --json.

Expected

  • show reports the local config path, approvals path, and effective merged policy.
  • preset yolo updates both tools.exec.* and approvals defaults to permissive local values.
  • set updates both stores consistently using explicit flags.

Actual

  • Behavior matches the expectations above in targeted CLI tests.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: added and ran targeted CLI tests for show, preset yolo, explicit set, and subcommand registration.
  • Edge cases checked: invalid input rejection is handled in the command parser; preset flow and explicit flag flow both update the two local stores.
  • What you did not verify: I did not manually exercise the command against a live operator config outside the mocked CLI test harness, and I did not verify remote gateway/node mutation because this PR does not implement it.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No)
    • Yes
  • Config/env changes? (Yes/No)
    • No
  • Migration needed? (Yes/No)
    • No
  • If yes, exact upgrade steps:
    • N/A

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk:
    • Reviewers may assume exec-policy also updates remote gateway or node-host state.
    • Mitigation:
      • The command implementation and PR description both call out the local-only scope explicitly.
  • Risk:
    • The new command could drift from existing approvals / effective-policy semantics over time.
    • Mitigation:
      • It reuses the existing exec-policy scope snapshot helper and targeted CLI tests cover the synchronized flows.

@aisle-research-bot

aisle-research-bot Bot commented Apr 10, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 2 potential security issue(s) in this PR:

# Severity Title
1 🟡 Medium Terminal escape/control sequence injection via unsanitized JSON output in exec-policy CLI
2 🟡 Medium Non-atomic exec-policy sync can leave approvals in a more permissive state when config update fails
1. 🟡 Terminal escape/control sequence injection via unsanitized JSON output in exec-policy CLI
Property Value
Severity Medium
CWE CWE-150
Location src/cli/exec-policy-cli.ts:374-434

Description

The exec-policy CLI emits JSON to stdout via defaultRuntime.writeJson(...) without applying sanitizeTerminalText/sanitizeExecApprovalDisplayText to string fields sourced from local config/approvals snapshots.

While JSON.stringify escapes many C0 control characters (e.g., \n, \u001b for ESC), it does not guarantee escaping of C1 control bytes (U+007F–U+009F), including sequences like U+009B (CSI) that some terminals interpret as control/escape sequences. If an attacker can influence fields like:

  • configPath / approvalsPath (filesystem paths)
  • scopeLabel (derived from approvals file keys / scope labels)
  • requestedSource / hostSource strings

then running exec-policy ... --json directly in a terminal (or piping to logs that are later viewed in terminals) can result in terminal spoofing/log injection.

Vulnerable code:

if (opts.json) {
  defaultRuntime.writeJson(payload, 0);
  return;
}

Recommendation

Harden JSON output intended for terminal/log viewing by neutralizing control characters in all string fields before writing.

Options:

  1. Sanitize JSON payload strings with a replacer that escapes C0 and C1 control characters:
function sanitizeForJsonTerminal(value: unknown): unknown {
  if (typeof value === "string") {// match sanitizeTerminalText behavior, but preserve JSON semantics
    return value
      .replace(/\r/g, "\\r")
      .replace(/\n/g, "\\n")
      .replace(/\t/g, "\\t")
      .replace(/[\u0000-\u001F\u007F-\u009F]/g, (c) =>
        `\\u{${c.codePointAt(0)!.toString(16).toUpperCase()}}`,
      );
  }
  if (Array.isArray(value)) return value.map(sanitizeForJsonTerminal);
  if (value && typeof value === "object") {
    return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, sanitizeForJsonTerminal(v)]));
  }
  return value;
}// when emitting JSON to stdout
defaultRuntime.writeJson(sanitizeForJsonTerminal(payload), 0);
  1. Alternatively, clearly document that --json is machine-readable and not terminal-safe, and provide a separate --json-safe mode (or make safe output the default).

This prevents terminal/log escape sequence interpretation when untrusted strings are present.

2. 🟡 Non-atomic exec-policy sync can leave approvals in a more permissive state when config update fails
Property Value
Severity Medium
CWE CWE-362
Location src/cli/exec-policy-cli.ts:336-360

Description

applyLocalExecPolicy() updates the host approvals file before updating config, and only rolls approvals back on config-write failure if the current approvals file hash still matches what it just wrote.

This creates a non-atomic update window:

  • Step 1: approvals are written (saveExecApprovals(nextApprovals))
  • Step 2: config update is attempted (replaceConfigFile(...))
  • If step 2 fails, rollback occurs only if the approvals file content hash is unchanged.

A local attacker/process running under the same user account (or a competing instance) can:

  • Force the config update to fail (e.g., by racing config changes, permissions, or other filesystem conditions causing replaceConfigFile to throw)
  • Modify the approvals file after it is written (even trivially, e.g., whitespace), causing currentApprovalsSnapshot.hash !== writtenApprovalsHash
  • Prevent rollback, leaving the approvals file at the new (potentially more permissive) settings while the config remains old.

Depending on the previous state, this can result in an unintended relaxation of the effective exec policy. For example, if config previously requested security=full but approvals were deny, a failed attempt to apply the cautious preset will write approvals to allowlist; if the config write fails and rollback is prevented, the effective policy becomes allowlist (less restrictive than before).

Recommendation

Make the update of config + approvals atomic (or at least fail-safe) so a config-write failure cannot leave approvals more permissive than before.

Options:

  1. Write config first, then approvals (preferred if config is the requested-policy side):

    • Attempt replaceConfigFile() first
    • Only after success, write approvals
    • If approvals write fails, either roll back config or clearly surface that the sync is incomplete
  2. Two-phase commit with temporary files + atomic renames:

    • Prepare both nextConfig and nextApprovals into temp files
    • Atomically swap them in a controlled sequence, with a journal/marker to recover on crash
  3. If you keep the current order, ensure rollback is not bypassable by minor modifications:

    • Use an OS-level lock (advisory lock) during the whole sync, or
    • Write a backup file and always restore it on config failure (even if approvals changed), but only after verifying ownership/permissions and notifying the user about concurrent modifications.

Example (write config first):

await replaceConfigFile({ baseHash: configSnapshot.hash, nextConfig });
saveExecApprovals(nextApprovals);

If approvals must be written first, use a lock around both writes to prevent races.


Analyzed PR: #64050 at commit 90e8615

Last updated on: 2026-04-10T06:10:29Z

@openclaw-barnacle openclaw-barnacle Bot added cli CLI command changes size: L maintainer Maintainer-authored PR labels Apr 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe0cd124ef

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts Outdated
@greptile-apps

greptile-apps Bot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds an openclaw exec-policy CLI with show, preset, and set subcommands that synchronize tools.exec.* config and ~/.openclaw/exec-approvals.json together in one step. The scope is explicitly local-only; remote gateway/node mutation is deferred. The implementation is logically sound: validation, config mutation, and approvals save are correctly sequenced, and the final buildLocalExecPolicyShowPayload re-reads both stores from disk so the displayed state reflects what was actually written. All remaining findings are P2 style nits.

Confidence Score: 5/5

Safe to merge; all findings are minor style suggestions with no production impact.

No P0 or P1 issues found. The three comments are P2: a duplicate import that can be merged, an unnecessary Promise.resolve() wrapper, and a double-exit design smell that only manifests in test scenarios (and no error-path tests exist to trigger it). Core logic — read → compute → mutate config → save approvals → re-read for display — is correct.

src/cli/exec-policy-cli.ts (minor style nits only)

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/cli/exec-policy-cli.ts
Line: 2-3

Comment:
**Duplicate import from same module**

Both statements import from `../config/config.js` and can be merged into one.

```suggestion
import { mutateConfigFile, readConfigFileSnapshot } from "../config/config.js";
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/cli/exec-policy-cli.ts
Line: 151-154

Comment:
**Unnecessary `Promise.resolve()` wrapper around synchronous call**

`readExecApprovalsSnapshot()` is synchronous (imported without `async`, mock confirms it). Wrapping it in `Promise.resolve()` adds no value and slightly obscures that the call is synchronous.

```suggestion
  const [configSnapshot, approvalsSnapshot] = await Promise.all([
    readConfigFileSnapshot(),
    readExecApprovalsSnapshot(),
  ]);
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/cli/exec-policy-cli.ts
Line: 262-267

Comment:
**`exitWithError` inside `try/catch` causes double-exit in test scenarios**

`exitWithError` calls `defaultRuntime.exit(1)` then `throw`s so TypeScript sees it as `never`. In production `process.exit` terminates immediately and the catch block is never reached. In tests, however, the mocked `exit` throws `Error("__exit__:1")`, which propagates to the outer `catch (err)` block, causing a second `defaultRuntime.error("Error: __exit__:1")` and a second `defaultRuntime.exit(1)`. Any future error-path tests for this command would see unexpected extra calls to `error` and `exit`, making assertions harder to write.

The same pattern appears in the `set` command's `Object.keys(policy).length === 0` check (line 300). Consider either re-throwing a sentinel `ExitError` that the catch recognizes and skips re-logging, or moving the `exitWithError` invocations outside the `try` scope.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat: add local exec-policy CLI" | Re-trigger Greptile

Comment thread src/cli/exec-policy-cli.ts Outdated
Comment thread src/cli/exec-policy-cli.ts Outdated
Comment thread src/cli/exec-policy-cli.ts

Copy link
Copy Markdown
Contributor Author

Follow-up pushed in 003daa219f.

Changes from review:

  • fixed the exec-policy show terminal-rendering hardening by sanitizing untrusted table cell content before it reaches renderTable()
  • cleaned up the duplicate import / synchronous snapshot read
  • removed the double-exit pattern and added focused regression coverage for both sanitization and the invalid-input error path

I did not expand this PR into a shared saveExecApprovals() rewrite. The symlink/atomic-write point is valid, but that function is existing shared infra used outside this new command. I’d rather land the CLI feature with the output hardening here and handle the file-write hardening as a dedicated follow-up so we can test the broader behavior change properly.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 003daa219f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: beaa25fdca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts Outdated
@Takhoffman
Takhoffman requested a review from a team as a code owner April 10, 2026 03:59
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Apr 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70d3bb9869

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts Outdated

Copy link
Copy Markdown
Contributor Author

Following up on the latest Aisle refresh against 411cfe96a6.

I am not fixing the three newly reported TOCTOU/permission findings in this feature PR:

  • ensureDir() check ordering / side-effectful mkdirSync before validation
  • raw rollback potentially recreating the approvals file with default permissions
  • the remaining directory-swap TOCTOU window before renameSync

Reason: those are all deeper shared saveExecApprovals() hardening questions, not exec-policy-specific behavior. I already took this PR as far as I’m comfortable for feature-adjacent hardening by fixing the rollback state preservation, newline-safe rendering, and home-subtree symlink traversal checks. I don’t want to widen a local CLI feature PR into a broader file-writer redesign without dedicated review.

The inline codex threads are replied to directly now:

  • requested host display: addressed in 8a0a5572f8
  • all-or-nothing rollback gap: addressed in 411cfe96a6
  • missing-file/raw rollback preservation: addressed in 411cfe96a6

If we want the remaining Aisle items fixed, I’d handle them as a separate hardening PR scoped specifically to src/infra/exec-approvals.ts.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 411cfe96a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 358aa27191

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/infra/exec-approvals.ts Outdated
@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams agents Agent runtime and tooling labels Apr 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6cef726bba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli/exec-policy-cli.ts Outdated
wongcyrus pushed a commit to wongcyrus/openclaw that referenced this pull request Apr 10, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
steipete pushed a commit that referenced this pull request Apr 10, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
ksylvan pushed a commit to ksylvan/openclaw that referenced this pull request Apr 11, 2026
The `assertNoSymlinkPathComponents` function introduced in openclaw#64050 rejects
any symlink encountered while walking from $HOME to the exec-approvals
file. This breaks setups where `~/.openclaw` itself is a symlink (e.g.
managed via GNU Stow for config backup).

Use `fs.realpathSync` to resolve the trusted root through top-level
symlinks before walking child segments. Symlinks *inside* the resolved
root are still rejected. The "."-segment self-check on the root is
removed since the root is now always the real path.

Update test: the "symlinked parent" case now expects success instead of
an error, and a new test verifies that symlinks inside the resolved home
are still caught.
btc69m979y-dotcom added a commit to netease-youdao/LobsterAI that referenced this pull request Apr 17, 2026
…s rejection

OpenClaw v2026.4.14 introduced assertNoSymlinkPathComponents() in
exec-approvals.ts (openclaw/openclaw#64050, commit 4bf94aa0d6,
2026-04-10) which rejects any symlink found along the exec approvals
path. In dev mode, vendor/openclaw-runtime/current is a symlink to
win-x64, causing the gateway to throw:

  "Refusing to traverse symlink in exec approvals path"

Fix by calling fs.realpathSync() on the resolved runtime root so the
gateway receives the real physical path instead of the symlink.

Only affects dev mode — packaged builds use process.resourcesPath/cfmind
(a real directory) and are not impacted.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Bojun-Vvibe added a commit to Bojun-Vvibe/openclaw that referenced this pull request Apr 27, 2026
The exec-approvals symlink hardening from openclaw#72377 still rejected a
symlinked ~/.openclaw immediate child of the trusted home directory,
breaking exec-policy commands for users who manage OpenClaw config via
GNU Stow, chezmoi, or other dotfile managers. openclaw#72377 only relaxed the
restriction on the OPENCLAW_HOME root itself.

Allow exactly one trusted symlink hop at the immediate child of the
trusted home root, but only when the realpath target is owned by the
current effective user AND is not group/other writable. Deeper symlinks
inside the resolved .openclaw tree, additional symlink hops, and
unsafe-permission targets remain rejected with the original error
message.

Updates the existing 'refuses to traverse symlinked approvals
components below a symlinked home' test to construct an unsafe target
(group-writable) so the deeper-symlink rejection intent of openclaw#72377 is
still exercised, and adds a new test for the safe-symlink case from
this issue.

Fixes openclaw#72572
Refines openclaw#72377, openclaw#64663, openclaw#64050
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* feat: add local exec-policy CLI

* fix: harden exec-policy CLI output

* fix: harden exec approvals writes

* fix: tighten local exec-policy sync

* docs: document exec-policy CLI

* fix: harden exec-policy rollback and approvals path checks

* fix: reject exec-policy sync when host remains node

* fix: validate approvals path before mkdir

* fix: guard exec-policy rollback against newer approvals writes

* fix: restore exec approvals via hardened rollback path

* fix: guard exec-policy config writes with base hash

* docs: add exec-policy changelog entry

* fix: clarify exec-policy show for node host

* fix: strip stale exec-policy decisions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling channel: msteams Channel integration: msteams cli CLI command changes docs Improvements or additions to documentation maintainer Maintainer-authored PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant