From 50cb027a88abcd83dd054e8ba917df9e6c3f596e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 9 May 2026 14:59:27 +0100 Subject: [PATCH] docs: document trusted skill symlink targets --- docs/gateway/configuration-examples.md | 21 ++++++++++++ docs/gateway/troubleshooting.md | 47 ++++++++++++++++++++++++++ docs/tools/skills-config.md | 27 +++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/docs/gateway/configuration-examples.md b/docs/gateway/configuration-examples.md index e81c96a2834..00aa40c38bb 100644 --- a/docs/gateway/configuration-examples.md +++ b/docs/gateway/configuration-examples.md @@ -447,6 +447,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number. allowBundled: ["gemini", "peekaboo"], load: { extraDirs: ["~/Projects/agent-scripts/skills"], + allowSymlinkTargets: ["~/Projects/agent-scripts/skills"], }, install: { preferBrew: true, @@ -464,6 +465,26 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number. } ``` +### Symlinked sibling skill repo + +Use this when a built-in skill root contains a symlink into a sibling repo, for +example `~/.agents/skills/manager -> ~/Projects/manager/skills`. + +```json5 +{ + skills: { + load: { + extraDirs: ["~/Projects/manager/skills"], + allowSymlinkTargets: ["~/Projects/manager/skills"], + }, + }, +} +``` + +- `extraDirs` scans the sibling repo as an explicit skill root. +- `allowSymlinkTargets` lets symlinked skill folders resolve into that trusted + real target root without allowing arbitrary symlink escapes. + ## Common patterns ### Shared skill baseline with one override diff --git a/docs/gateway/troubleshooting.md b/docs/gateway/troubleshooting.md index 5a712529755..4ac95ad0564 100644 --- a/docs/gateway/troubleshooting.md +++ b/docs/gateway/troubleshooting.md @@ -62,6 +62,53 @@ openclaw config get meta.lastTouchedVersion For intentional downgrade or emergency recovery only, set `OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1` for the single command. Leave it unset for normal operation. +## Skill symlink skipped as path escape + +Use this when logs include: + +```text +Skipping escaped skill path outside its configured root: ... reason=symlink-escape +``` + +OpenClaw treats every skill root as a containment boundary. A symlink under +`~/.agents/skills`, `/.agents/skills`, `/skills`, or +`~/.openclaw/skills` is skipped when its real target resolves outside that root +unless the target is explicitly trusted. + +Inspect the link: + +```bash +ls -l ~/.agents/skills/ +realpath ~/.agents/skills/ +openclaw config get skills.load +``` + +If the target is intentional, configure both the direct skill root and the +allowed symlink target: + +```json5 +{ + skills: { + load: { + extraDirs: ["~/Projects/manager/skills"], + allowSymlinkTargets: ["~/Projects/manager/skills"], + }, + }, +} +``` + +Then start a new session or wait for the skills watcher to refresh. Restart the +gateway if the running process predates the config change. + +Do not use broad targets such as `~`, `/`, or a whole synced project folder. +Keep `allowSymlinkTargets` scoped to the real skill root that contains trusted +`SKILL.md` directories. + +Related: + +- [Skills config](/tools/skills-config#symlinked-sibling-repos) +- [Configuration examples](/gateway/configuration-examples#symlinked-sibling-skill-repo) + ## Anthropic 429 extra usage required for long context Use this when logs/errors include: `HTTP 429: rate_limit_error: Extra usage is required for long context requests`. diff --git a/docs/tools/skills-config.md b/docs/tools/skills-config.md index dfc9573a01f..b94e9b6dbac 100644 --- a/docs/tools/skills-config.md +++ b/docs/tools/skills-config.md @@ -107,6 +107,33 @@ Rules: - `agents.list[].skills`: optional per-agent final skill allowlist; explicit lists replace inherited defaults instead of merging. +## Symlinked sibling repos + +By default, each skill root is a containment boundary. If a skill folder under +`~/.agents/skills` is a symlink that resolves outside `~/.agents/skills`, +OpenClaw skips it and logs `Skipping escaped skill path outside its configured +root`. + +Keep the symlink layout and allow only the trusted target root: + +```json5 +{ + skills: { + load: { + extraDirs: ["~/Projects/manager/skills"], + allowSymlinkTargets: ["~/Projects/manager/skills"], + }, + }, +} +``` + +With this config, a symlink such as +`~/.agents/skills/manager -> ~/Projects/manager/skills` is accepted after +realpath resolution. `extraDirs` also scans the sibling repo directly, while +`allowSymlinkTargets` preserves the symlinked path for existing agent-skill +layouts. Keep target entries narrow; do not point at broad roots such as `~` or +`~/Projects` unless every skill tree under that root is trusted. + Per-skill fields: - `enabled`: set `false` to disable a skill even if it's bundled/installed.