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
- Create a symlink:
ln -s ../ehoy/.claude/skills/my-skill ~/.openclaw/workspace/skills/my-skill
(where ehoy/ is another directory inside the workspace)
- Run
openclaw security audit → no findings related to this symlink
- 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 132794f) 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
Description
The
skills.workspace.symlink_escapeaudit probe checks whether skill file realpaths escape the workspace root (~/.openclaw/workspace/), but the skill loader (resolveContainedSkillPathinsrc/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:
openclaw security audit(no finding)Steps to Reproduce
ln -s ../ehoy/.claude/skills/my-skill ~/.openclaw/workspace/skills/my-skill(where
ehoy/is another directory inside the workspace)openclaw security audit→ no findings related to this symlinkExpected Behavior
openclaw security auditshould 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 132794f) 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
Relates to #49408