xtekky/gpt4free · error · PermissionError
Invalid file path: '{file}'
Error message
Invalid file path: '{file}' What it means
Raised by the sandbox open() shim when Path(file).resolve() itself raises ValueError or OSError — i.e. the path is malformed before any containment check happens. Typical causes: embedded NUL bytes, paths too long for the OS, or (on Windows) paths with invalid characters or nonexistent drive roots. The original exception is chained via 'from exc'.
Source
Thrown at g4f/mcp/pa_provider.py:543
k: getattr(_builtins, k) for k in dir(_builtins) if k not in _blocked
}
# Provide a workspace-scoped open()
def _safe_open(file, mode="r", *args, **kwargs):
"""open() restricted to the workspace directory."""
path = Path(file)
if not path.is_absolute():
path = workspace / path
try:
resolved = path.resolve()
ws_resolved = workspace.resolve()
if not str(resolved).startswith(str(ws_resolved)):
raise PermissionError(
f"File access outside workspace is denied: '{file}'. "
f"Workspace: {workspace}"
)
except (ValueError, OSError) as exc:
raise PermissionError(f"Invalid file path: '{file}'") from exc
return open(resolved, mode, *args, **kwargs)
safe_builtins["open"] = _safe_open
safe_builtins["__import__"] = _make_restricted_import(allowed)
# Override print / input so stdout/stderr stay local to this sandbox
# execution and are never written to the real sys.stdout/stderr. This
# avoids the global-state side-effect that contextlib.redirect_stdout
# would cause when the thread is abandoned after a timeout.
if stdout_buf is not None:
_real_print = _builtins.print
def _safe_print(*args, **kwargs):
kwargs.setdefault("file", stdout_buf)
_real_print(*args, **kwargs)
safe_builtins["print"] = _safe_print
View on GitHub (pinned to 973504e177)
Solutions
- Sanitize filenames before open(): strip control characters and NULs
- Print/log the exact file value to find which call site produced the bad path
- Construct paths with pathlib.Path components instead of string concatenation
Example fix
# before
name = user_input # may contain \x00
open(name)
# after
name = user_input.replace('\x00', '')
open(name) Defensive patterns
Strategy: validation
Validate before calling
def safe_filename(name: str) -> str:
return ''.join(ch for ch in name if ord(ch) > 31 and ch not in '<>:"/\\|?*') Try / catch
try:
f = open(user_path)
except PermissionError as e:
if "Invalid file path" in str(e):
user_path = safe_filename(user_path); f = open(user_path) Prevention
- Sanitize any filename derived from user/LLM input before open()
- Build paths with pathlib.Path instead of string concatenation
- Log the offending path value when this fires to find the bad producer
When it happens
Trigger: open('data\x00.json'), an extremely long relative path that exceeds PATH_MAX during resolution, or a path containing characters the filesystem API rejects so that resolve() throws OSError/ValueError.
Common situations: Binary data or user input containing NUL bytes concatenated into a filename; machine-generated paths from LLM-written provider code; cross-platform scripts with Windows-invalid characters (* ? " < > |) in names.
Related errors
- File access outside workspace is denied: '{file}'. Workspace
- Syntax error in workspace module '{name}' ({source_path}):\n
- Failed to load workspace module '{name}' ({source_path}):\n{
- Relative imports are not allowed inside a .pa.py sandbox.
- '{name}' is not available in the restricted os shim.
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/40e9ef8dbce52555.
Report an issue: GitHub.