Review feedback from @trek-e — three blocking issues and one style fix:
1. **Symlink escape guard** — Added validatePath() call on the resolved
global skill path with allowAbsolute: true. This routes the path
through the existing symlink-resolution and containment logic in
security.cjs, preventing a skill directory symlinked to an arbitrary
location from being injected. The name regex alone prevented
traversal in the literal name but not in the underlying directory.
2. **5 new tests** covering the global: code path:
- global:valid-skill resolves and appears in output
- global:invalid!name rejected by regex, skipped without crash
- global:missing-skill (directory absent) skipped gracefully
- Mix of global: and project-relative paths both resolve
- global: with empty name produces clear warning and skips
3. **Explicit empty-name guard** — Added before the regex check so
"global:" produces "empty skill name" instead of the confusing
'Invalid global skill name ""'.
4. **Style fix** — Hoisted require('os') and globalSkillsBase
calculation out of the loop, alongside the existing validatePath
import at the top of buildAgentSkillsBlock.
All 16 agent-skills tests pass.
12 KiB
12 KiB