Update Modules/File_System.py
Browse files- Modules/File_System.py +28 -20
Modules/File_System.py
CHANGED
|
@@ -146,27 +146,11 @@ def _resolve_path(path: str) -> tuple[str, str]:
|
|
| 146 |
if not ALLOW_ABS:
|
| 147 |
try:
|
| 148 |
common = os.path.commonpath([os.path.normpath(ROOT_DIR), os.path.normpath(abs_path)])
|
|
|
|
|
|
|
| 149 |
except Exception:
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
abs_cmp = os.path.normcase(os.path.normpath(abs_path))
|
| 153 |
-
if not abs_cmp.startswith(root_cmp):
|
| 154 |
-
return "", _err(
|
| 155 |
-
"path_outside_root",
|
| 156 |
-
"Path not allowed outside root.",
|
| 157 |
-
path=user_input.replace("\\", "/"),
|
| 158 |
-
hint="Use a path under / (the tool's root)."
|
| 159 |
-
)
|
| 160 |
-
else:
|
| 161 |
-
root_cmp = os.path.normcase(os.path.normpath(ROOT_DIR))
|
| 162 |
-
common_cmp = os.path.normcase(os.path.normpath(common))
|
| 163 |
-
if common_cmp != root_cmp:
|
| 164 |
-
return "", _err(
|
| 165 |
-
"path_outside_root",
|
| 166 |
-
"Path not allowed outside root.",
|
| 167 |
-
path=user_input.replace("\\", "/"),
|
| 168 |
-
hint="Use a path under / (the tool's root)."
|
| 169 |
-
)
|
| 170 |
return abs_path, ""
|
| 171 |
except Exception as exc:
|
| 172 |
return "", _err(
|
|
@@ -177,6 +161,30 @@ def _resolve_path(path: str) -> tuple[str, str]:
|
|
| 177 |
)
|
| 178 |
|
| 179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
def _fmt_size(num_bytes: int) -> str:
|
| 181 |
units = ["B", "KB", "MB", "GB", "TB"]
|
| 182 |
size = float(num_bytes)
|
|
|
|
| 146 |
if not ALLOW_ABS:
|
| 147 |
try:
|
| 148 |
common = os.path.commonpath([os.path.normpath(ROOT_DIR), os.path.normpath(abs_path)])
|
| 149 |
+
if common != os.path.normpath(ROOT_DIR):
|
| 150 |
+
return "", _err("path_outside_root", "Path is outside the sandbox root.", path=abs_path)
|
| 151 |
except Exception:
|
| 152 |
+
return "", _err("path_outside_root", "Path is outside the sandbox root.", path=abs_path)
|
| 153 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
return abs_path, ""
|
| 155 |
except Exception as exc:
|
| 156 |
return "", _err(
|
|
|
|
| 161 |
)
|
| 162 |
|
| 163 |
|
| 164 |
+
def safe_open(file, *args, **kwargs):
|
| 165 |
+
"""
|
| 166 |
+
A drop-in replacement for open() that enforces sandbox constraints.
|
| 167 |
+
"""
|
| 168 |
+
# Handle integer file descriptors (pass through) or bytes (decode)
|
| 169 |
+
if isinstance(file, int):
|
| 170 |
+
return open(file, *args, **kwargs)
|
| 171 |
+
|
| 172 |
+
path_str = os.fspath(file)
|
| 173 |
+
abs_path, err = _resolve_path(path_str)
|
| 174 |
+
if err:
|
| 175 |
+
# Extract message from JSON error if possible
|
| 176 |
+
try:
|
| 177 |
+
msg = json.loads(err)["message"]
|
| 178 |
+
except:
|
| 179 |
+
msg = err
|
| 180 |
+
raise PermissionError(f"Sandboxed open() failed: {msg}")
|
| 181 |
+
|
| 182 |
+
return open(abs_path, *args, **kwargs)
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
|
| 188 |
def _fmt_size(num_bytes: int) -> str:
|
| 189 |
units = ["B", "KB", "MB", "GB", "TB"]
|
| 190 |
size = float(num_bytes)
|