fix: harden workspace skill discovery

This commit is contained in:
Soulter
2026-06-19 00:59:40 +08:00
parent 0dfa481f0d
commit 6de93fd69f
2 changed files with 42 additions and 6 deletions

View File

@@ -353,17 +353,24 @@ class SkillManager:
if not workspace_root:
return []
skills_root = Path(workspace_root) / WORKSPACE_SKILLS_ROOT
raw_workspace_root = Path(workspace_root)
skills_root = raw_workspace_root / WORKSPACE_SKILLS_ROOT
if not skills_root.is_dir():
return []
try:
resolved_workspace_root = raw_workspace_root.resolve(strict=True)
resolved_skills_root = skills_root.resolve(strict=True)
if not resolved_skills_root.is_relative_to(resolved_workspace_root):
return []
skill_dirs = sorted(
resolved_skills_root.iterdir(), key=lambda item: item.name
)
except OSError:
return []
skills: list[SkillInfo] = []
for skill_dir in sorted(skills_root.iterdir(), key=lambda item: item.name):
for skill_dir in skill_dirs:
if not skill_dir.is_dir():
continue
skill_name = skill_dir.name

View File

@@ -4,6 +4,8 @@ from __future__ import annotations
from pathlib import Path
import pytest
from astrbot.core.skills.skill_manager import (
SkillInfo,
SkillManager,
@@ -526,10 +528,7 @@ def test_list_workspace_skills_reads_frontmatter_with_limit(tmp_path: Path):
skill_dir = workspace_root / "skills" / "large-skill"
skill_dir.mkdir(parents=True)
skill_dir.joinpath("SKILL.md").write_text(
"---\n"
"description: Large workspace skill.\n"
"---\n"
+ ("x" * (128 * 1024)),
"---\ndescription: Large workspace skill.\n---\n" + ("x" * (128 * 1024)),
encoding="utf-8",
)
@@ -540,6 +539,36 @@ def test_list_workspace_skills_reads_frontmatter_with_limit(tmp_path: Path):
assert skills[0].description == "Large workspace skill."
def test_list_workspace_skills_rejects_symlinked_root_outside_workspace(
tmp_path: Path,
):
skills_root = tmp_path / "skills"
plugins_root = tmp_path / "plugins"
workspace_root = tmp_path / "workspace"
external_root = tmp_path / "external-skills"
skills_root.mkdir(parents=True, exist_ok=True)
plugins_root.mkdir(parents=True, exist_ok=True)
workspace_root.mkdir(parents=True, exist_ok=True)
external_skill = external_root / "external-skill"
external_skill.mkdir(parents=True)
external_skill.joinpath("SKILL.md").write_text(
"---\ndescription: Outside workspace.\n---\n",
encoding="utf-8",
)
try:
workspace_root.joinpath("skills").symlink_to(
external_root,
target_is_directory=True,
)
except OSError as exc:
pytest.skip(f"Directory symlinks are unavailable: {exc}")
mgr = SkillManager(skills_root=str(skills_root), plugins_root=str(plugins_root))
assert mgr.list_workspace_skills(workspace_root) == []
def test_list_skills_includes_plugin_provided_skills(monkeypatch, tmp_path: Path):
import astrbot.core.star.star as star_module
from astrbot.core.star.star import StarMetadata