From dbaa2f3638f690c0a6c26237e1485228f9c49473 Mon Sep 17 00:00:00 2001 From: Rip&Tear <84775494+theCyberTech@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:37:44 +0800 Subject: [PATCH] test: fix portability issues in path traversal tests - test_blocks_traversal_in_filename: use a sibling temp dir instead of asserting against a potentially pre-existing ../outside.txt - test_blocks_absolute_path_in_filename: use a temp-dir-derived absolute path instead of hardcoding /etc/passwd - test_blocks_symlink_escape: symlink to a temp "outside" dir instead of /etc, assert target file was not created Co-Authored-By: Claude Sonnet 4.6 --- .../tests/tools/test_file_writer_tool.py | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/crewai-tools/tests/tools/test_file_writer_tool.py b/lib/crewai-tools/tests/tools/test_file_writer_tool.py index 38e23db9f..eb816ee38 100644 --- a/lib/crewai-tools/tests/tools/test_file_writer_tool.py +++ b/lib/crewai-tools/tests/tools/test_file_writer_tool.py @@ -140,33 +140,54 @@ def test_file_exists_error_handling(tool, temp_env, overwrite): # --- Path traversal prevention --- def test_blocks_traversal_in_filename(tool, temp_env): - result = tool._run( - filename="../outside.txt", - directory=temp_env["temp_dir"], - content="should not be written", - overwrite=True, - ) - assert "Error" in result - assert not os.path.exists(os.path.join(temp_env["temp_dir"], "../outside.txt")) + # Create a sibling "outside" directory so we can assert nothing was written there. + outside_dir = tempfile.mkdtemp() + outside_file = os.path.join(outside_dir, "outside.txt") + try: + result = tool._run( + filename=f"../{os.path.basename(outside_dir)}/outside.txt", + directory=temp_env["temp_dir"], + content="should not be written", + overwrite=True, + ) + assert "Error" in result + assert not os.path.exists(outside_file) + finally: + shutil.rmtree(outside_dir, ignore_errors=True) def test_blocks_absolute_path_in_filename(tool, temp_env): - result = tool._run( - filename="/etc/passwd", - directory=temp_env["temp_dir"], - content="should not be written", - overwrite=True, - ) - assert "Error" in result + # Use a temp file outside temp_dir as the absolute target so we don't + # depend on /etc/passwd existing or being writable on the host. + outside_dir = tempfile.mkdtemp() + outside_file = os.path.join(outside_dir, "target.txt") + try: + result = tool._run( + filename=outside_file, + directory=temp_env["temp_dir"], + content="should not be written", + overwrite=True, + ) + assert "Error" in result + assert not os.path.exists(outside_file) + finally: + shutil.rmtree(outside_dir, ignore_errors=True) def test_blocks_symlink_escape(tool, temp_env): + # Symlink inside temp_dir pointing to a separate temp "outside" directory. + outside_dir = tempfile.mkdtemp() + outside_file = os.path.join(outside_dir, "target.txt") link = os.path.join(temp_env["temp_dir"], "escape") - os.symlink("/etc", link) - result = tool._run( - filename="escape/crontab", - directory=temp_env["temp_dir"], - content="should not be written", - overwrite=True, - ) - assert "Error" in result + os.symlink(outside_dir, link) + try: + result = tool._run( + filename="escape/target.txt", + directory=temp_env["temp_dir"], + content="should not be written", + overwrite=True, + ) + assert "Error" in result + assert not os.path.exists(outside_file) + finally: + shutil.rmtree(outside_dir, ignore_errors=True)