Skip to content

fix(daemon): harden launchd plist with umask 077#31919

Merged
steipete merged 2 commits intoopenclaw:mainfrom
liuxiaopai-ai:codex/launchd-umask-hardening-31905
Mar 2, 2026
Merged

fix(daemon): harden launchd plist with umask 077#31919
steipete merged 2 commits intoopenclaw:mainfrom
liuxiaopai-ai:codex/launchd-umask-hardening-31905

Conversation

@liuxiaopai-ai
Copy link
Copy Markdown
Contributor

Summary

  • Problem: LaunchAgent plist regeneration during upgrades could drop Umask and revert daemon-created file permissions to world-readable defaults.
  • Why it matters: Gateway state files created after update may be broader than intended until a later security audit/fix pass.
  • What changed: Added a hardened default Umask=077 to generated macOS gateway LaunchAgent plist output.
  • What changed: Added regression assertion to launchd install tests to lock Umask emission in generated plist.
  • What did NOT change (scope boundary): No changes to launchctl lifecycle commands, non-macOS services, or environment-token handling logic.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • 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

User-visible / Behavior Changes

  • openclaw gateway install on macOS now writes LaunchAgent plist entries with Umask set to 077 (decimal 63), preserving owner-only default file creation behavior after upgrades.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS-targeted path (validated by unit tests)
  • Runtime/container: daemon launchd service install path
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): default gateway install flow

Steps

  1. Run LaunchAgent plist generation through daemon install path.
  2. Inspect generated plist contents.
  3. Verify KeepAlive/Throttle + new Umask key are present.

Expected

  • Generated plist contains Umask with decimal value 63 (octal 077).

Actual

  • Matches expected after patch.

Evidence

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

Human Verification (required)

  • Verified scenarios:
    • src/daemon/launchd.test.ts now asserts Umask exists in generated plist.
    • Existing launchd install/restart ordering assertions continue passing.
  • Edge cases checked:
    • Non-macOS service paths untouched.
    • Existing plist fields (KeepAlive, ThrottleInterval, env dict) unaffected.
  • What you did not verify:
    • Live end-to-end install on a macOS host in this PR run.

Compatibility / Migration

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

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
    • Revert this commit.
  • Files/config to restore:
    • src/daemon/launchd-plist.ts
    • src/daemon/launchd.test.ts
  • Known bad symptoms reviewers should watch for:
    • Missing Umask key in newly generated LaunchAgent plist files.

Risks and Mitigations

  • Risk: Some operators may expect permissive default file modes from launchd-managed gateway writes.
    • Mitigation: 077 is a security-hardening default aligned with existing owner-only expectations for gateway state; change is limited to macOS LaunchAgent generation.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

Adds Umask=077 (decimal 63) to macOS LaunchAgent plist generation to ensure gateway-created files default to owner-only permissions (mode 600) after upgrades. The change introduces a new constant LAUNCH_AGENT_UMASK_DECIMAL defined as 0o077 and adds the corresponding key-value pair to the plist template in buildLaunchAgentPlist().

Key changes:

  • Added LAUNCH_AGENT_UMASK_DECIMAL = 0o077 constant in src/daemon/launchd-plist.ts
  • Inserted <key>Umask</key> entry with decimal value 63 in generated plist XML
  • Added regression test assertions to verify Umask presence in generated plists
  • Updated CHANGELOG.md with appropriate entry

Security impact:

  • Prevents gateway state files from being created with world-readable permissions after npm upgrades
  • Aligns with security best practices for daemon-created files
  • Only affects newly generated plists (backward compatible)

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The change is simple, well-tested, and implements a valid security hardening measure. The implementation correctly uses octal notation (0o077) for the constant while ensuring it's interpolated as decimal (63) in the plist. Test coverage includes regression assertions for both the key and value. The change is scoped appropriately to macOS LaunchAgent generation only and doesn't affect existing behavior or other platforms.
  • No files require special attention

Last reviewed commit: d748b87

@steipete steipete force-pushed the codex/launchd-umask-hardening-31905 branch from d748b87 to 49b6dc4 Compare March 2, 2026 18:13
@steipete steipete merged commit 718d418 into openclaw:main Mar 2, 2026
9 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented Mar 2, 2026

Landed via temp rebase onto main.

  • Gate: bunx vitest run src/daemon/launchd.test.ts
  • Land commit: LAND_SHA_PLACEHOLDER
  • Merge commit: MERGE_SHA_PLACEHOLDER

Thanks @liuxiaopai-ai!

@steipete
Copy link
Copy Markdown
Contributor

steipete commented Mar 2, 2026

Corrected SHA details for landed rebase flow:

  • Gate: bunx vitest run src/daemon/launchd.test.ts
  • Land commit: 49b6dc4
  • Merge commit: 718d418

Thanks @liuxiaopai-ai!

execute008 pushed a commit to execute008/openclaw that referenced this pull request Mar 2, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 17, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
(cherry picked from commit 718d418)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 17, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
(cherry picked from commit 718d418)
alexey-pelykh added a commit to remoteclaw/remoteclaw that referenced this pull request Mar 17, 2026
* fix(security): harden tar archive extraction parity

(cherry picked from commit 0dbb92d)

* fix: harden sandbox writes and centralize atomic file writes

(cherry picked from commit 18f8393)

* refactor(security): split sandbox media staging and stream safe copies

(cherry picked from commit 4a80311)

* fix(security): harden workspace bootstrap boundary reads

(cherry picked from commit 07b16d5)

* fix: harden webhook auth-before-body handling

(cherry picked from commit d3e8b17)

* refactor(security): unify hardened install and fs write flows

(cherry picked from commit d4bf07d)

* fix(security): harden zip write race handling

(cherry picked from commit 7dac9b0)

* refactor(security): split gateway auth suites and share safe write path checks

(cherry picked from commit 83c8406)

* fix(daemon): harden launchd plist with umask 077 (openclaw#31919)

* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
(cherry picked from commit 718d418)

* test(guardrails): exclude suite files and harden auth temp identity naming

(cherry picked from commit a8fe8b6)

* fix: harden plugin command registration + telegram menu guard (openclaw#31997) (thanks @liuxiaopai-ai)

(cherry picked from commit ee68fa8)

* fix: rebrand openclaw refs from cherry-picks

* fix: adapt cherry-picks for fork TS strictness

- bluebubbles/monitor.test.ts: OpenClawConfig → RemoteClawConfig (rebrand miss)
- bluebubbles/monitor.ts, googlechat/monitor.ts: registerWebhookTargetWithPluginRoute →
  registerWebhookTarget (upstream refactored function not in fork plugin-sdk)
- sandbox/workspace.test.ts: remove orphaned test for gutted sandbox workspace module
- skills-install-extract.ts: fix hasBinary import from deleted skills.js → shared/config-eval.js
- fs-safe.ts: add missing pipeline import, OPEN_WRITE_*_FLAGS constants,
  assertNoPathAliasEscape stub, and openVerifiedLocalFile options parameter
- fs-safe.test.ts: add missing writeFileWithinRoot/copyFileWithinRoot/writeFileFromPathWithinRoot
  imports from fs-safe.js
- install-safe-path.ts: add assertCanonicalPathWithinBase (upstream definition from unmerged PR)
- install-package-dir.ts: add missing assertCanonicalPathWithinBase import

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix: wire hardlink rejection in openFileWithinRoot

* fix(security): unify root-bound write hardening

(cherry picked from commit 104d32b)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Mark L <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
lukeg826 pushed a commit to lukeg826/openclaw that referenced this pull request Mar 26, 2026
* fix(daemon): add launchd umask hardening

* fix: finalize launchd umask changelog + thanks (openclaw#31919) (thanks @liuxiaopai-ai)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]:LaunchD plist regeneration drops Umask — gateway writes world-readable files after update

2 participants