openclaw - ✅(Solved) Fix [Bug]: security audit symlink_escape probe uses wrong boundary (workspace root vs skills directory) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60145Fetched 2026-04-08 02:35:46
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×1

The skills.workspace.symlink_escape audit probe checks whether skill file realpaths escape the workspace root (~/.openclaw/workspace/), but the skill loader (resolveContainedSkillPath in src/agents/skills/workspace.ts) checks against the skills directory root (~/.openclaw/workspace/skills/).

This creates a gap where symlinks that resolve inside the workspace but outside the skills directory are:

  • Passed by openclaw security audit (no finding)
  • Silently rejected by the skill loader (skill not loaded, no error)

Error Message

  • Silently rejected by the skill loader (skill not loaded, no error)

Root Cause

The audit probe was added on March 2 (commit 132794fe) before the loader hardening shipped on March 8 (v2026.3.7). The probe checked against the workspace root, which was correct at the time, but the loader was subsequently tightened to check against the skills directory root. The audit probe was not updated to match.

Fix Action

Fix

PR #60144 updates the audit probe to use the skills directory realpath as its boundary, matching the loader.

PR fix notes

PR #60155: fix(security): align audit symlink_escape boundary with skill loader

Description (problem / solution / changelog)

Problem

The skills.workspace.symlink_escape audit probe checks whether workspace skill realpaths escape the workspace root, but the skill loader (resolveContainedSkillPath) checks whether they escape the skills directory root (workspace/skills/). This creates a gap where symlinks that resolve inside the workspace but outside the skills directory pass the audit but are silently rejected at load time.

Example: workspace/skills/my-skill -> ../shared/skills/my-skill resolves to workspace/shared/skills/my-skill — inside the workspace root (audit passes ✅) but outside workspace/skills/ (loader rejects ❌).

Impact

We had 10 symlinked skills silently invisible for nearly a month. The daily-review cron skill stopped working reliably when v2026.3.7 shipped the loader enforcement — but openclaw security audit never flagged it. The model compensated by discovering the skill file through manual filesystem search ~80% of the time, masking the issue.

Fix

Align the audit probe boundary with the loader: check against the skills directory root, not the workspace root. One-line logic change + updated finding messages + test for the gap case.

Changes

  • audit-extra.async.ts: resolve skillsDir (workspace/skills) instead of workspacePath, use it as the containment boundary
  • audit.test.ts: add test case for symlink inside workspace but outside skills dir
  • Updated finding title/detail/remediation to reference "skills directory" instead of "workspace root"
  • Added skills.load.extraDirs mention in remediation text

CI Note

Windows test failures in task-owner-access.test.ts are pre-existing timeouts, unrelated to this change.

Closes #60145

Changed files

  • src/security/audit-extra.async.ts (modified, +7/-5)
  • src/security/audit.test.ts (modified, +30/-1)
RAW_BUFFERClick to expand / collapse

Description

The skills.workspace.symlink_escape audit probe checks whether skill file realpaths escape the workspace root (~/.openclaw/workspace/), but the skill loader (resolveContainedSkillPath in src/agents/skills/workspace.ts) checks against the skills directory root (~/.openclaw/workspace/skills/).

This creates a gap where symlinks that resolve inside the workspace but outside the skills directory are:

  • Passed by openclaw security audit (no finding)
  • Silently rejected by the skill loader (skill not loaded, no error)

Steps to Reproduce

  1. Create a symlink: ln -s ../ehoy/.claude/skills/my-skill ~/.openclaw/workspace/skills/my-skill (where ehoy/ is another directory inside the workspace)
  2. Run openclaw security audit → no findings related to this symlink
  3. The skill never loads — it is silently dropped

Expected Behavior

openclaw security audit should flag symlinks whose realpath escapes the skills directory (workspace/skills/), matching the loader's actual boundary check.

Impact

We had 10 symlinked skills silently invisible for nearly a month. The daily-review cron skill stopped working around March 8 (when v2026.3.7 shipped the realpath enforcement). We spent days debugging inconsistent behavior — the model was finding and executing skills through manual filesystem search ~80% of the time, masking that formal skill discovery never included them.

Root Cause

The audit probe was added on March 2 (commit 132794fe) before the loader hardening shipped on March 8 (v2026.3.7). The probe checked against the workspace root, which was correct at the time, but the loader was subsequently tightened to check against the skills directory root. The audit probe was not updated to match.

Fix

PR #60144 updates the audit probe to use the skills directory realpath as its boundary, matching the loader.

Environment

  • OpenClaw v2026.4.2
  • macOS (Apple Silicon)

Relates to #49408

extent analysis

TL;DR

Update the skills.workspace.symlink_escape audit probe to check against the skills directory root (~/.openclaw/workspace/skills/) instead of the workspace root.

Guidance

  • Review the resolveContainedSkillPath function in src/agents/skills/workspace.ts to understand the loader's boundary check.
  • Verify that the audit probe is updated to match the loader's check by ensuring it uses the skills directory realpath as its boundary.
  • Test the updated audit probe with symlinks that resolve inside the workspace but outside the skills directory to ensure they are correctly flagged.
  • Consider backporting the fix to earlier versions of OpenClaw to prevent similar issues in the future.

Example

No code snippet is provided as the issue already mentions the fix in PR #60144.

Notes

The fix assumes that updating the audit probe to match the loader's boundary check will resolve the issue. However, additional testing may be necessary to ensure that the fix does not introduce any new issues.

Recommendation

Apply the workaround by updating the audit probe to use the skills directory realpath as its boundary, as this will ensure consistency between the audit probe and the loader's boundary check.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING