Skip to content

[BUG] Two path-containment security tests fail on Windows without symlink privilege #7431

Description

@iam-kira

Description

Two tests in lib/crewai-tools create symlinks in setup with no guard, so they fail on Windows for any user who is not elevated and does not have Developer Mode enabled:

OSError: [WinError 1314] A required privilege is not held by the client
tests/utilities/test_safe_path.py:53 — test_rejects_symlink_escape
os.symlink("/etc/passwd", str(link))
tests/tools/test_file_writer_tool.py:216 — test_blocks_symlink_escape
os.symlink(outside_dir, link)
Both are security regression tests — they assert that a symlink cannot be used to escape the allowed directory. So the practical effect is that the two tests guarding crewAI's path-containment (the same behaviour hardened in #6248 and #6249) are exactly the ones an ordinary Windows contributor cannot run; their suite comes back red in setup.

Steps to Reproduce

Why CI doesn't catch it

The workflow matrix runs ubuntu-latest and macos-*; no job runs the suite on Windows. GitHub's runners can create symlinks anyway, so even a Windows job would pass — the gap is a privilege one, not just a platform one.

Expected behavior

The product code is fine

Worth stating so this isn't mistaken for a security report: validate_file_path in lib/crewai-tools/src/crewai_tools/security/safe_path.py uses os.path.realpath() then a prefix containment check. realpath() resolves junctions as well as symlinks on Windows, so the containment itself holds. This is only about the tests being unable to run.

Screenshots/Code snippets

Operating System

Ubuntu 20.04

Python Version

3.10

crewAI Version

crewAI Tools Version

Virtual Environment

Venv

Evidence

..

Possible Solution

Suggested fix (happy to PR once this is triaged)
A small helper that skips only the privilege case and re-raises every other OSError, so a genuine setup failure never turns into a passing skip:

def _symlink_or_skip(src, dst):
try:
os.symlink(src, dst)
except OSError as e:
if os.name == "nt" and getattr(e, "winerror", None) == 1314:
pytest.skip("symlink creation requires elevated privileges on Windows")
raise
Used at the two call sites. Where symlinks work — every current CI job, and any elevated or Developer Mode machine — behaviour is unchanged, and the escape assertions still run.

Additional context

Environment
Windows 11 (10.0.26200), Python 3.13, non-elevated, Developer Mode off
crewAI at HEAD (lib/crewai-tools)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions