Skip to content

test(skill_manager): update sandbox cache path expectations #5706

Open
RC-CHN wants to merge 3 commits intoAstrBotDevs:masterfrom
RC-CHN:master
Open

test(skill_manager): update sandbox cache path expectations #5706
RC-CHN wants to merge 3 commits intoAstrBotDevs:masterfrom
RC-CHN:master

Conversation

@RC-CHN
Copy link
Member

@RC-CHN RC-CHN commented Mar 3, 2026

修复单元测试skill部分

Modifications / 改动点

修正 sandbox 路径断言,强化“sandbox 缓存技能不可停用”的权限校验,新增 show_sandbox_path=False 的覆盖测试。

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

image

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

Summary by Sourcery

更新技能管理器沙箱缓存测试,以匹配新的路径解析行为和沙箱技能的权限规则。

Bug 修复:

  • list_skills 测试中,更正对内置技能的预期沙箱技能路径。
  • 使测试与以下规则保持一致:沙箱缓存的技能不能被停用,尝试停用时应抛出 PermissionError

测试:

  • show_sandbox_pathFalse 时,增加对沙箱和本地路径解析的覆盖,以确保本地覆盖生效并正确暴露路径。
Original summary in English

Summary by Sourcery

Update skill manager sandbox cache tests to match new path resolution behavior and permission rules for sandboxed skills.

Bug Fixes:

  • Correct expected sandbox skill path for built-in skills in list_skills tests.
  • Align tests with the rule that sandbox-cached skills cannot be deactivated and should raise PermissionError when attempted.

Tests:

  • Add coverage for sandbox and local path resolution when show_sandbox_path is False, ensuring local overrides and correct path exposure.

RC-CHN added 2 commits March 3, 2026 16:24
adjust sandbox cache tests to match absolute path resolution in
list_skills for sandbox runtime.

verify sandbox-cached skills cannot be deactivated via set_skill_active
by asserting a PermissionError, and keep active-only listing behavior
intact.

add coverage for show_sandbox_path=false to ensure local skills still
override cached metadata while sandbox-only skills retain cached paths.
@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Mar 3, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the unit tests for the skill manager's sandbox cache functionality. It corrects path assertions for sandbox skills, enforces that sandbox cached skills cannot be deactivated by raising a "PermissionError", and introduces a new test to validate skill path resolution when the "show_sandbox_path" option is disabled.

Highlights

  • Test Path Expectations: Updated the expected path for sandbox cached skills in tests to reflect the full workspace path.
  • Permission Validation: Strengthened permission validation in tests to ensure that sandbox cached skills cannot be deactivated, asserting a "PermissionError".
  • New Test Case: Added a new test to verify correct path resolution for both local and sandbox skills when "show_sandbox_path" is set to "False".
Changelog
  • tests/test_skill_manager_sandbox_cache.py
    • Imported the "pytest" module for advanced testing capabilities.
    • Adjusted the expected path assertion for 'python-sandbox' skill to include the full '/workspace/' prefix.
    • Modified the "test_sandbox_cached_skill_respects_active_and_display_path" test to catch "PermissionError" when attempting to deactivate a sandbox skill.
    • Introduced a new test function "test_sandbox_and_local_path_resolution_with_show_sandbox_path_false" to cover scenarios where sandbox paths are not explicitly displayed.
Activity
  • The author, RC-CHN, initiated this pull request to fix issues in the skill unit tests.
  • The PR description outlines specific modifications including correcting sandbox path assertions, strengthening permission checks for sandbox skills, and adding a new test for "show_sandbox_path=False".
  • A screenshot demonstrating test results was provided by the author.
  • The author completed a checklist confirming that the changes are not breaking, well-tested, do not introduce new dependencies, and contain no malicious code.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added the area:core The bug / feature is about astrbot's core, backend label Mar 3, 2026
@dosubot
Copy link

dosubot bot commented Mar 3, 2026

Related Documentation

Checked 1 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题

给 AI 代理的提示
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tests/test_skill_manager_sandbox_cache.py" line_range="111-120" />
<code_context>
+def test_sandbox_and_local_path_resolution_with_show_sandbox_path_false(
</code_context>
<issue_to_address>
**suggestion (testing):** 收紧本地 skill 的路径断言,确保它确实使用本地根路径,而不是只是因为后缀匹配而误通过

在这个测试中,当前的 `endswith("/skills/custom-local/SKILL.md")` 检查,即使 sandbox 路径和本地路径共享相同后缀时也可能通过。为了增强鲁棒性,还应断言解析后的路径位于 `skills_root` 之下(例如通过 `startswith(str(skills_root))`,或者使用一个小的兼容 helper 通过 `Path(...).is_relative_to(skills_root)` 进行判断)。
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据这些反馈改进后续的评审。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tests/test_skill_manager_sandbox_cache.py" line_range="111-120" />
<code_context>
+def test_sandbox_and_local_path_resolution_with_show_sandbox_path_false(
</code_context>
<issue_to_address>
**suggestion (testing):** Tighten the path assertion for the local skill to ensure it truly uses the local root instead of accidentally matching by suffix

In this test, the current `endswith("/skills/custom-local/SKILL.md")` check could still pass if the sandbox and local paths share the same suffix. To harden it, also assert that the resolved path is under `skills_root` (e.g., `startswith(str(skills_root))` or `Path(...).is_relative_to(skills_root)` via a small compat helper).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +111 to +120
def test_sandbox_and_local_path_resolution_with_show_sandbox_path_false(
monkeypatch,
tmp_path: Path,
):
data_dir = tmp_path / "data"
temp_dir = tmp_path / "temp"
skills_root = tmp_path / "skills"
data_dir.mkdir(parents=True, exist_ok=True)
temp_dir.mkdir(parents=True, exist_ok=True)
skills_root.mkdir(parents=True, exist_ok=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): 收紧本地 skill 的路径断言,确保它确实使用本地根路径,而不是只是因为后缀匹配而误通过

在这个测试中,当前的 endswith("/skills/custom-local/SKILL.md") 检查,即使 sandbox 路径和本地路径共享相同后缀时也可能通过。为了增强鲁棒性,还应断言解析后的路径位于 skills_root 之下(例如通过 startswith(str(skills_root)),或者使用一个小的兼容 helper 通过 Path(...).is_relative_to(skills_root) 进行判断)。

Original comment in English

suggestion (testing): Tighten the path assertion for the local skill to ensure it truly uses the local root instead of accidentally matching by suffix

In this test, the current endswith("/skills/custom-local/SKILL.md") check could still pass if the sandbox and local paths share the same suffix. To harden it, also assert that the resolved path is under skills_root (e.g., startswith(str(skills_root)) or Path(...).is_relative_to(skills_root) via a small compat helper).

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR updates unit tests for the SkillManager, focusing on correcting sandbox path assertions, adding tests for the rule that 'sandbox cached skills cannot be deactivated', and new coverage tests for show_sandbox_path=False. While the code changes are correct and the new tests are valuable, it's critical to address a confirmed behavior in the core logic: untrusted paths from the sandbox cache are exposed when show_sandbox_path is False. This exposure, combined with insufficient sanitization in prompt construction, creates a potential prompt injection and path traversal vulnerability. On a positive note, the PR correctly implements a permission check to prevent deactivating sandbox-only skills, which is a good security improvement. For improved test code maintainability, consider using pytest fixtures to reduce duplication.

assert sorted(by_name) == ["custom-local", "python-sandbox"]
assert by_name["custom-local"].description == "local description"
local_skill_path = Path(by_name["custom-local"].path)
assert local_skill_path.is_relative_to(skills_root)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

This test case confirms that when show_sandbox_path is set to False, the SkillManager.list_skills method returns the untrusted path directly from the sandbox cache for sandbox-only skills. Tracing this data flow to build_skills_prompt in astrbot/core/skills/skill_manager.py reveals that these paths are included in the system prompt with minimal sanitization (only backticks are used for wrapping, and the _SAFE_PATH_RE sanitization is only applied to the example path, not the full list).

An attacker who can manipulate the sandbox cache (e.g., via a compromised sandbox environment) could inject malicious instructions or path traversal sequences into the system prompt. For example, a path like ` \n\n **SYSTEM INSTRUCTION**: ... could break out of the backticks and manipulate the LLM's behavior. Furthermore, if the LLM is instructed to read these files via shell commands (as suggested in the prompt rules), it could lead to information disclosure if the commands are executed on the host.

To remediate this, the list_skills logic should be updated to avoid returning untrusted cache paths when show_sandbox_path is False, and build_skills_prompt should rigorously sanitize all skill metadata (names, descriptions, and paths) before embedding them in the prompt.

Comment on lines +115 to +129
data_dir = tmp_path / "data"
temp_dir = tmp_path / "temp"
skills_root = tmp_path / "skills"
data_dir.mkdir(parents=True, exist_ok=True)
temp_dir.mkdir(parents=True, exist_ok=True)
skills_root.mkdir(parents=True, exist_ok=True)

monkeypatch.setattr(
"astrbot.core.skills.skill_manager.get_astrbot_data_path",
lambda: str(data_dir),
)
monkeypatch.setattr(
"astrbot.core.skills.skill_manager.get_astrbot_temp_path",
lambda: str(temp_dir),
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这段测试设置代码在多个测试函数中重复出现(test_list_skills_merges_local_and_sandbox_cache, test_sandbox_cached_skill_respects_active_and_display_path, 以及这个新的测试)。为了提高代码的可维护性并减少重复,建议将这部分逻辑提取到一个 pytest fixture 中。

例如,你可以创建一个 fixture:

import pytest
from pathlib import Path

@pytest.fixture
def skills_root(monkeypatch, tmp_path: Path) -> Path:
    data_dir = tmp_path / "data"
    temp_dir = tmp_path / "temp"
    skills_root_path = tmp_path / "skills"
    data_dir.mkdir(parents=True, exist_ok=True)
    temp_dir.mkdir(parents=True, exist_ok=True)
    skills_root_path.mkdir(parents=True, exist_ok=True)

    monkeypatch.setattr(
        "astrbot.core.skills.skill_manager.get_astrbot_data_path",
        lambda: str(data_dir),
    )
    monkeypatch.setattr(
        "astrbot.core.skills.skill_manager.get_astrbot_temp_path",
        lambda: str(temp_dir),
    )
    
    return skills_root_path

然后在测试函数中使用它,这样可以移除重复的设置代码:

def test_sandbox_and_local_path_resolution_with_show_sandbox_path_false(skills_root: Path):
    mgr = SkillManager(skills_root=str(skills_root))
    # ... 测试的其余部分

这将使测试代码更简洁、更易于维护。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant