xtekky/gpt4free · error · PermissionError
File access outside workspace is denied: '{file}'. Workspace
Error message
File access outside workspace is denied: '{file}'. Workspace: {workspace} What it means
Raised by the sandbox's replacement open() when the requested path resolves outside the workspace directory. The shim resolves both the target and the workspace root and denies any target whose resolved path string does not start with the workspace prefix, confining .pa.py file I/O to the workspace. Note the check is a plain string prefix, so a sibling directory sharing a prefix (e.g. /ws-evil next to /ws) would also pass — a known weakness of this style of check.
Source
Thrown at g4f/mcp/pa_provider.py:538
# Build a reduced copy of the real built-ins
_blocked = frozenset(
{"exec", "eval", "compile", "input", "breakpoint", "__import__"}
)
safe_builtins: Dict[str, Any] = {
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):View on GitHub (pinned to 973504e177)
Solutions
- Use relative paths — they are joined onto the workspace root by the shim
- Store any cache/credentials inside the workspace directory (e.g. open('cache.json', 'w'))
- Pass file contents in as strings/parameters instead of reading external files
Example fix
# before
open('/home/user/tokens.json')
# after
open('tokens.json') # resolves inside the workspace dir Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def is_in_workspace(candidate, workspace: Path) -> bool:
resolved = (workspace / candidate).resolve() if not Path(candidate).is_absolute() else Path(candidate).resolve()
ws = workspace.resolve()
return resolved == ws or str(resolved).startswith(str(ws) + str(Path('/').sep))
# note: use the sep-terminated prefix to avoid the sibling-dir bypass Try / catch
try:
with open(target) as f:
data = f.read()
except PermissionError as e:
if "outside workspace" in str(e):
data = None # re-point the path into the workspace Prevention
- Always use workspace-relative paths in .pa.py files
- Keep caches, tokens and state files inside the workspace directory
- Never hard-code absolute paths in sandboxed provider code
When it happens
Trigger: open('/etc/passwd'), open('../../secrets.txt'), or any absolute/relative path whose resolved location is not under the workspace directory. Also triggered on Windows when drive letters or .. traversal escape the workspace.
Common situations: Provider code writing cache/token files to a hard-coded absolute path; using '..' to reach project files; scripts developed outside the sandbox that read config from $HOME.
Related errors
- '{name}' is not available in the restricted os shim.
- Import of '{name}' is not allowed in safe execution mode.\nA
- Invalid file path: '{file}'
- har_and_cookies dir is not readable
- Syntax error in workspace module '{name}' ({source_path}):\n
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/1adf169616ac968b.
Report an issue: GitHub.