From 73a88a02fe4d8947936da34b3bb88ba7a36f8281 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Mon, 23 Mar 2026 16:00:34 -0700 Subject: [PATCH] fix(security): prevent shell injection in _expand_path via ~user path suffix (#2047) echo was called with the full unquoted path (~username/suffix), allowing command substitution in the suffix (e.g. ~user/$(malicious)) to execute arbitrary shell commands. The fix expands only the validated ~username portion via the shell and concatenates the suffix as a plain string. Co-authored-by: Gutslabs --- tools/file_operations.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/file_operations.py b/tools/file_operations.py index 56ed1319f..e13a26170 100644 --- a/tools/file_operations.py +++ b/tools/file_operations.py @@ -433,9 +433,13 @@ class ShellFileOperations(FileOperations): slash_idx = rest.find('/') username = rest[:slash_idx] if slash_idx >= 0 else rest if username and re.fullmatch(r'[a-zA-Z0-9._-]+', username): - expand_result = self._exec(f"echo {path}") + # Only expand ~username (not the full path) to avoid shell + # injection via path suffixes like "~user/$(malicious)". + expand_result = self._exec(f"echo ~{username}") if expand_result.exit_code == 0 and expand_result.stdout.strip(): - return expand_result.stdout.strip() + user_home = expand_result.stdout.strip() + suffix = path[1 + len(username):] # e.g. "/rest/of/path" + return user_home + suffix return path