Skip to content

fix: guard workspace umo normalization#9006

Open
tangtaizong666 wants to merge 2 commits into
AstrBotDevs:masterfrom
tangtaizong666:fix/umo-workspace-normalization-pr
Open

fix: guard workspace umo normalization#9006
tangtaizong666 wants to merge 2 commits into
AstrBotDevs:masterfrom
tangtaizong666:fix/umo-workspace-normalization-pr

Conversation

@tangtaizong666

@tangtaizong666 tangtaizong666 commented Jun 25, 2026

Copy link
Copy Markdown

Summary

  • guard normalize_umo_for_workspace() against dot-only or separator-only values
  • add regression coverage proving workspace_root("..") stays under the configured workspaces directory
  • preserve existing normal UMO names such as qq:GroupMessage:1000 and platform.user-1

Why

Per-session computer workspaces are derived from normalized UMO values. Values such as . or .. previously survived normalization and could resolve to the workspaces directory itself or its parent instead of a per-session child directory.

Tests

  • UV_PROJECT_ENVIRONMENT=/tmp/astrbot-venv-8755 uv run pytest -q tests/unit/test_computer_workspace_util.py
  • UV_PROJECT_ENVIRONMENT=/tmp/astrbot-venv-8755 uv run pytest -q tests/test_computer_fs_tools.py tests/unit/test_message_tools.py
  • UV_PROJECT_ENVIRONMENT=/tmp/astrbot-venv-8755 uv run ruff format --check .
  • UV_PROJECT_ENVIRONMENT=/tmp/astrbot-venv-8755 uv run ruff check .

Summary by Sourcery

Guard workspace UMO normalization against unsafe dot-only values and ensure workspace roots remain confined under the configured workspaces directory.

Bug Fixes:

  • Prevent dot-only or separator-only UMO values from resolving to the workspaces directory or its parent by mapping them to an "unknown" workspace name.

Tests:

  • Add unit tests covering normalization of typical UMO session names, rejection of dot-only values, and workspace_root behavior to keep sessions under the workspaces directory.

@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend labels Jun 25, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Consider extracting the "unknown" workspace name to a shared constant and documenting the intended behavior for separator-only UMOs, so that callers and future changes don’t accidentally rely on or diverge from this sentinel value.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider extracting the "unknown" workspace name to a shared constant and documenting the intended behavior for separator-only UMOs, so that callers and future changes don’t accidentally rely on or diverge from this sentinel value.

## Individual Comments

### Comment 1
<location path="tests/unit/test_computer_workspace_util.py" line_range="24-33" />
<code_context>
+    assert computer_util.normalize_umo_for_workspace(" _._ ") == "unknown"
+
+
+def test_workspace_root_for_dot_only_umo_stays_under_workspaces(
+    monkeypatch,
+    tmp_path: Path,
+) -> None:
+    workspaces_root = tmp_path / "workspaces"
+    monkeypatch.setattr(
+        computer_util,
+        "get_astrbot_workspaces_path",
+        lambda: str(workspaces_root),
+    )
+
+    root = computer_util.workspace_root("..")
+
+    assert root == (workspaces_root / "unknown").resolve(strict=False)
+    assert root.is_relative_to(workspaces_root.resolve(strict=False))
</code_context>
<issue_to_address>
**suggestion (testing):** Extend `workspace_root` regression coverage to other unsafe UMO values, not just `".."`.

The existing test validates `workspace_root("..")` correctly. To cover the full set of risky UMO values mentioned in the PR, please add/parameterize tests for other dot-only and separator-only inputs (e.g. ".", "...", " _._ ", and values that normalize to only separators). For each case, assert both the resolved path (e.g. `<workspaces_root>/unknown`) and that it remains within `workspaces_root` to prevent future path traversal regressions.

Suggested implementation:

```python
@pytest.mark.parametrize(
    "unsafe_umo",
    [
        ".",
        "..",
        "...",
        " _._ ",
        "/",
        "//",
        " / / ",
    ],
)
def test_workspace_root_for_unsafe_umo_stays_under_workspaces(
    unsafe_umo: str,
    monkeypatch,
    tmp_path: Path,
) -> None:
    workspaces_root = tmp_path / "workspaces"
    monkeypatch.setattr(
        computer_util,
        "get_astrbot_workspaces_path",
        lambda: str(workspaces_root),
    )

    root = computer_util.workspace_root(unsafe_umo)

    assert root == (workspaces_root / "unknown").resolve(strict=False)
    assert root.is_relative_to(workspaces_root.resolve(strict=False))

```

1. Ensure `pytest` is imported at the top of this test module: `import pytest`.
2. If `normalize_umo_for_workspace`’s behavior for separator-only inputs differs (e.g., not mapping to `"unknown"`), you may want to mirror or adjust the set of `unsafe_umo` values in this parametrization to exactly match the “risky” cases defined in the implementation or elsewhere in the PR.
</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 +24 to +33
def test_workspace_root_for_dot_only_umo_stays_under_workspaces(
monkeypatch,
tmp_path: Path,
) -> None:
workspaces_root = tmp_path / "workspaces"
monkeypatch.setattr(
computer_util,
"get_astrbot_workspaces_path",
lambda: str(workspaces_root),
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion (testing): Extend workspace_root regression coverage to other unsafe UMO values, not just "..".

The existing test validates workspace_root("..") correctly. To cover the full set of risky UMO values mentioned in the PR, please add/parameterize tests for other dot-only and separator-only inputs (e.g. ".", "...", " . ", and values that normalize to only separators). For each case, assert both the resolved path (e.g. <workspaces_root>/unknown) and that it remains within workspaces_root to prevent future path traversal regressions.

Suggested implementation:

@pytest.mark.parametrize(
    "unsafe_umo",
    [
        ".",
        "..",
        "...",
        " _._ ",
        "/",
        "//",
        " / / ",
    ],
)
def test_workspace_root_for_unsafe_umo_stays_under_workspaces(
    unsafe_umo: str,
    monkeypatch,
    tmp_path: Path,
) -> None:
    workspaces_root = tmp_path / "workspaces"
    monkeypatch.setattr(
        computer_util,
        "get_astrbot_workspaces_path",
        lambda: str(workspaces_root),
    )

    root = computer_util.workspace_root(unsafe_umo)

    assert root == (workspaces_root / "unknown").resolve(strict=False)
    assert root.is_relative_to(workspaces_root.resolve(strict=False))
  1. Ensure pytest is imported at the top of this test module: import pytest.
  2. If normalize_umo_for_workspace’s behavior for separator-only inputs differs (e.g., not mapping to "unknown"), you may want to mirror or adjust the set of unsafe_umo values in this parametrization to exactly match the “risky” cases defined in the implementation or elsewhere in the PR.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a check in normalize_umo_for_workspace to handle strings that only contain separator characters, returning 'unknown' in those cases, and adds corresponding unit tests. The reviewer suggests simplifying the return statement by removing the redundant or "unknown" fallback, as separator-only and empty strings are already handled by the new check.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

normalized = re.sub(r"[^A-Za-z0-9._-]+", "_", umo.strip())
if not normalized.strip("._-"):
return "unknown"
return normalized or "unknown"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The or "unknown" fallback is redundant here because any empty or purely separator-based normalized string is already caught and handled by the if not normalized.strip("._-"): check on line 11. Simplifying this to return normalized improves readability.

Suggested change
return normalized or "unknown"
return normalized

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:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant