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)
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)