Skip to content

fix(security): route temp workspaces through private OpenClaw temp root (#101224)#101246

Merged
steipete merged 5 commits into
openclaw:mainfrom
yangxiansheng:fix/issue-101224-tmp-dir-perm-mutation
Jul 7, 2026
Merged

fix(security): route temp workspaces through private OpenClaw temp root (#101224)#101246
steipete merged 5 commits into
openclaw:mainfrom
yangxiansheng:fix/issue-101224-tmp-dir-perm-mutation

Conversation

@yangxiansheng

@yangxiansheng yangxiansheng commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes #101224

What Problem This Solves

Fixes an issue where running openclaw skills install or openclaw skills update could change /tmp permissions from 0o1777 (sticky + world-writable) to 0o0700 (owner-only), breaking access to the shared system temp directory for other processes and services. Affects Linux hosts where os.tmpdir() resolves to /tmp.

The same bug affects ClawHub plugin (openclaw plugins install clawhub:...) and package archive downloads via the same code path.

Why This Change Was Made

The root cause is that ClawHub skill and package download flows passed os.tmpdir() (/tmp) as the root directory to @openclaw/fs-safe temp workspaces, whose ensurePrivateDirectory helper calls chmod(root, 0o700) to enforce private permissions. When root is a shared OS directory like /tmp, this mutates system-level permissions.

The fix routes all temp workspace operations through resolvePreferredOpenClawTmpDir(), which returns the private /tmp/openclaw directory (or a user-scoped fallback {os.tmpdir()}/openclaw-{uid}). This directory is already owned by OpenClaw and has safe 0o700 permissions — changing its mode does not affect other system processes.

Six call sites were identified and unified: withTempDir's default root in install-source-utils.ts, and 5 explicit tmpDir: os.tmpdir() overrides in clawhub.ts covering ClawHub skill archive downloads, skill archive URL downloads, GitHub source archive downloads, and package archive downloads (both archive and ClawPack artifact paths). No external API changes, no new dependencies.

User Impact

ClawHub skill and plugin installation no longer risk corrupting /tmp permissions. All temporary workspace operations — ClawHub downloads, archive extraction staging, and git skill cloning — now consistently use the private OpenClaw temp root instead of raw /tmp. For most users this is invisible; for users running auditd or sharing a system with other services, /tmp sticky-bit and world-writable permissions are preserved.

Evidence

  • Source-reproducible audit trail: Issue reporter's auditd logs confirmed chmod syscalls on /tmp from the same process chain (openclaw-skills).

  • fs-safe source verification: Published @openclaw/[email protected] ensurePrivateDirectory calls fs.chmod(root, 0o700) on the provided rootDir.

  • Focused regression coverage: Added install-source-utils.chmod.test.ts that mocks an isolated parent temp root with 0o1777 permissions and verifies: (1) withTempDir uses the OpenClaw private temp root, and (2) the parent directory permissions remain unchanged (0o1777) after the temp workspace completes.

  • Test results (all pass):

    ✓ |infra| src/infra/install-source-utils.chmod.test.ts (1 test)
    ✓ |infra| src/infra/install-source-utils.test.ts (16 tests)
    ✓ |infra| src/infra/install-flow.test.ts (5 tests)
    ✓ |infra| src/infra/clawhub.test.ts (60 passed, 2 skipped)
    ✓ |infra| src/infra/tmp-openclaw-dir.test.ts (22 tests)
    ✓ |unit| src/skills/lifecycle/clawhub.test.ts (74 tests)
    
  • real behavior proof
    ✓ PASS: /tmp permissions unchanged (1777) — temp workspace correctly isolated under /tmp/openclaw (700)

Terminal output

[my openclaw]$ export OPENCLAW_CLAWHUB_TOKEN="my-token"
[my openclaw]$ stat -c "%a %A" /tmp
1777 drwxrwxrwt
[my openclaw]$ node openclaw.mjs skills install @steipete/github --acknowledge-clawhub-risk
│
◇  

OpenClaw 2026.6.11 (164d1bf) — Gateway online—please keep hands, feet, and appendages inside the shell at all times.

11:55:05 [state-migrations] Legacy state migration warnings:
- Left Codex binding sidecar in place because its session is owned by agent harness openclaw: /home/bili/.openclaw/agents/main/sessions/2017b93c-b47a-4ec8-9331-1e897b3f1019.jsonl.codex-app-server.json                                                                  
│
◇  Doctor warnings ────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                                                                                                      │
│  - Left Codex binding sidecar in place because its session is owned by agent harness                                 │
│    openclaw:                                                                                                         │
│    /home/bili/.openclaw/agents/main/sessions/2017b93c-b47a-4ec8-9331-1e897b3f1019.jsonl.codex-app-server.json  │
│                                                                                                                      │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Downloading [email protected] from ClawHub…
Installing to /home/bili/.openclaw/workspace/skills/github…
Installed [email protected] -> /home/bili/.openclaw/workspace/skills/github
[my openclaw]$ stat -c "%a %A" /tmp
1777 drwxrwxrwt
[my openclaw]$ stat -c "%a %A" /tmp/openclaw
700 drwx------


This PR is AI-assisted. Analysis, implementation, and testing were performed using opencode with human review by the author.

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 7, 2026, 1:20 AM ET / 05:20 UTC.

Summary
This PR routes ClawHub download and install-source temp workspaces through OpenClaw's existing private temp root and adds a POSIX permission regression test.

PR surface: Source -5, Tests +57. Total +52 across 3 files.

Reproducibility: yes. source-reproducible with high confidence. Current main passes raw /tmp into a dependency that chmods its root, the linked issue includes auditd proof, and the PR body includes after-fix terminal proof showing /tmp preserved.

Review metrics: 1 noteworthy metric.

  • Temp-root call sites: 1 default changed, 5 raw /tmp overrides removed. This quantifies the shared-temp permission fix because these six paths were the source-level ways install/download staging reached raw os.tmpdir().

Stored data model
Persistent data-model change detected: serialized state: src/infra/install-source-utils.chmod.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #101224
Summary: This PR is the candidate fix for the open issue reporting that OpenClaw skill install/update can change /tmp permissions from 1777 to 0700.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] The live PR is mergeable but behind base, and 3 exact-head checks were still in progress when inspected; this is a landing-gate risk, not a code finding.

Maintainer options:

  1. Decide the mitigation before merge
    Land this narrow private-temp-root fix after exact-head checks finish, then let the linked issue close from the merged PR and treat the broader sibling PR as non-canonical.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No ClawSweeper repair lane is needed; the remaining action is maintainer landing/review after exact-head checks finish.

Security
Cleared: The diff is security-positive and introduces no new dependency, workflow, secret-handling, package-resolution, or broader code-execution surface.

Review details

Best possible solution:

Land this narrow private-temp-root fix after exact-head checks finish, then let the linked issue close from the merged PR and treat the broader sibling PR as non-canonical.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible with high confidence. Current main passes raw /tmp into a dependency that chmods its root, the linked issue includes auditd proof, and the PR body includes after-fix terminal proof showing /tmp preserved.

Is this the best way to solve the issue?

Yes. Reusing the existing private OpenClaw temp-root resolver is the narrowest maintainable fix; restoring /tmp after mutation or weakening temp workspace privacy would be less reliable.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5d9a2b114f75.

Label changes

Label justifications:

  • P0: The paired issue reports install/update flows chmodding the shared /tmp directory to 0700, breaking unrelated system services and requiring urgent recovery.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes a terminal transcript showing /tmp at 1777 before and after a real ClawHub skill install, with /tmp/openclaw at 700 afterward.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes a terminal transcript showing /tmp at 1777 before and after a real ClawHub skill install, with /tmp/openclaw at 700 afterward.
Evidence reviewed

PR surface:

Source -5, Tests +57. Total +52 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 2 2 7 -5
Tests 1 57 0 +57
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 59 7 +52

What I checked:

Likely related people:

  • steipete: Live PR state assigns this review to steipete, and merged PR history ties steipete to the fs-safe extraction and temp-workspace surface. (role: feature-history owner and current PR assignee; confidence: high; commits: 90fd7822f2d3, 8eb9a3b2d472, a9e9a619d35f; files: src/infra/private-temp-workspace.ts, src/infra/tmp-openclaw-dir.ts, src/infra/clawhub.ts)
  • vincentkoc: Merged PR history shows recent ClawHub skill lifecycle hardening near the install/update surface affected by this bug. (role: recent ClawHub skills area contributor; confidence: medium; commits: ccb4100fc5a2; files: src/cli/skills-cli.ts, src/cli/skills-cli.commands.test.ts, src/skills/lifecycle/clawhub.test.ts)
  • RomneyDa: Merged PR history shows recent changes to src/infra/clawhub.ts and its tests around ClawHub request/download behavior. (role: recent ClawHub infra contributor; confidence: medium; commits: 7621081f3b7d, e1cd2d143d7a, 1f094b390d88; files: src/infra/clawhub.ts, src/infra/clawhub.test.ts)
  • Bartok9: Merged PR history shows recent git plugin staging work in install-source-utils and adjacent git install staging code. (role: recent install-source contributor; confidence: medium; commits: 1cf263a40365, 43ca9a0163f1; files: src/infra/install-source-utils.ts, src/plugins/git-install.ts, src/plugins/git-install.test.ts)
  • johnstormentswe: Merged PR history ties this account to prior tmp-openclaw-dir platform handling, which is the resolver this PR reuses. (role: adjacent temp-root contributor; confidence: medium; commits: 2411cad15ea5, 9bd61cbd796d, 6da9b07fbafe; files: src/infra/tmp-openclaw-dir.ts, src/infra/tmp-openclaw-dir.test.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-07T01:20:45.899Z sha ed7b392 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-07T02:40:54.402Z sha 9a07c76 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-07T03:35:31.256Z sha 164d1bf :: needs real behavior proof before merge. :: [P3] Assert the sticky bit in the permission regression
  • reviewed 2026-07-07T04:52:28.993Z sha 36d997f :: found issues before merge. :: [P1] Drop the unrelated second-commit payload
  • reviewed 2026-07-07T05:09:43.635Z sha 3e4fcf0 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. labels Jul 7, 2026
@yangxiansheng
yangxiansheng force-pushed the fix/issue-101224-tmp-dir-perm-mutation branch from ed7b392 to abd5daf Compare July 7, 2026 02:14
@yangxiansheng
yangxiansheng force-pushed the fix/issue-101224-tmp-dir-perm-mutation branch from abd5daf to 9a07c76 Compare July 7, 2026 02:29
@yangxiansheng

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 7, 2026
@yangxiansheng
yangxiansheng force-pushed the fix/issue-101224-tmp-dir-perm-mutation branch from 9a07c76 to 164d1bf Compare July 7, 2026 02:56
@yangxiansheng

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@steipete steipete self-assigned this Jul 7, 2026
@steipete
steipete requested a review from a team as a code owner July 7, 2026 04:40
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: signal Channel integration: signal channel: telegram Channel integration: telegram channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web app: android App: android app: ios App: ios labels Jul 7, 2026
@openclaw-barnacle openclaw-barnacle Bot added size: S and removed app: web-ui App: web-ui gateway Gateway runtime extensions: diagnostics-otel Extension: diagnostics-otel scripts Repository scripts commands Command implementations agents Agent runtime and tooling extensions: anthropic extensions: qa-lab extensions: codex size: XL labels Jul 7, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 automation 🚨 May affect CI, automerge, proof capture, label sync, or maintainer automation. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 7, 2026
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Prepared and land-ready at exact head 9ca89fe3da0749cdc85b45f5147497d0415fc4c6.

Work completed:

  • Routed the generic install workspace through OpenClaw's private temp root and removed all five ClawHub os.tmpdir() overrides.
  • Tightened the regression to assert exact parent mode 01777, private-root mode 0700, canonicalize the macOS temp path, and skip POSIX mode assertions on Windows.
  • Verified the final diff remains limited to the three intended infra files.

Validation:

Known proof gap: a separate maintainer sanitized-AWS attempt (cbx_af31296ffdaf) exhausted memory during dependency installation after AWS quota fell back to t3.small; it did not reach or execute PR code. The exact-head hosted Linux gates and focused regression are green.

@steipete
steipete merged commit 7db7487 into openclaw:main Jul 7, 2026
101 checks passed
@steipete

steipete commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: openclaw skills install changes /tmp permissions from 1777 to 0700

2 participants