Skip to content

[rajarshidattapy] fix: resolve workspace paths with realpath to block symlink escape (#135)#138

Open
rajarshidattapy wants to merge 1 commit into
openswarm-ai:mainfrom
rajarshidattapy:rajashidattapy/fix/outputs-symlink-path-traversal
Open

[rajarshidattapy] fix: resolve workspace paths with realpath to block symlink escape (#135)#138
rajarshidattapy wants to merge 1 commit into
openswarm-ai:mainfrom
rajarshidattapy:rajashidattapy/fix/outputs-symlink-path-traversal

Conversation

@rajarshidattapy

Copy link
Copy Markdown

Description

Fixes #135.

The Output workspace file endpoints (serve, seed, write, and delete) validated paths using a lexical os.path.normpath() prefix check. Because normpath() does not resolve symbolic links, a symlink placed inside a workspace could cause read, write, or delete operations to follow the link outside the workspace root.

Changes

  • Introduce a shared safe_workspace_path() helper that:
    • Resolves both the workspace root and target path using os.path.realpath()
    • Enforces containment with an os.sep boundary check
    • Detects escapes through intermediate symlink components
  • Route all four workspace file endpoints through the shared helper, replacing the three previously divergent normpath-based validation implementations.
  • Eliminate the sibling-prefix collision (abc vs. abc-evil) that previously affected the serve and seed paths by enforcing proper directory-boundary checks.

Validation

  • Added comprehensive regression tests in tests/test_outputs_workspace_path_traversal.py.
  • Symlink-specific tests are automatically skipped on platforms where symlink creation is unavailable (e.g. Windows without the required privileges) and execute in Linux CI.

…symlink escape (openswarm-ai#135)

The Output file endpoints (serve/seed/write/delete) gated paths with a
lexical os.path.normpath prefix check, which does not resolve symlinks — a
symlink inside a workspace redirected the read/write/delete outside it.

- Add safe_workspace_path(): one realpath-based containment helper (both
  sides realpath'd, `+ os.sep` boundary), returning None on escape.
- Route serve_workspace_file, the seed writer, write_workspace_file, and
  delete_workspace_file through it, replacing the three divergent normpath
  checks. Also closes the sibling-prefix collision (abc vs abc-evil) the
  serve/seed paths lacked.
- Add tests/test_outputs_workspace_path_traversal.py (symlink cases skip
  where the OS forbids symlink creation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rajarshidattapy rajarshidattapy changed the title fix: resolve workspace paths with realpath to block symlink escape (#135) [rajarshidattapy] fix: resolve workspace paths with realpath to block symlink escape (#135) Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Path-containment checks in Output file endpoints use os.path.normpath instead of realpath — symlinks escape the workspace (read/write/delete)

1 participant