Understanding Symphony's Path Safety System: Secure Workspace Isolation in OpenAI Symphony
Symphony's path safety system prevents directory traversal attacks by canonicalizing all workspace paths and validating they remain within configured root boundaries before any filesystem operations occur.
Symphony isolates each Codex job in a dedicated workspace on the host machine to prevent filesystem escape vulnerabilities. The path safety system, centered around the SymphonyElixir.PathSafety module, ensures that malicious symlinks or path traversal sequences cannot breach the workspace root directory. This mechanism is enforced across local operations and remote SSH executions, providing a unified security boundary for all workspace-related activities.
Core Mechanisms of the Path Safety System
Path Canonicalization
At the heart of the system lies the SymphonyElixir.PathSafety.canonicalize/1 function, implemented in elixir/lib/symphony_elixir/path_safety.ex (lines 4-16). This function resolves relative components (.., .) and symbolic links to determine the real filesystem location of any requested path.
The implementation expands the input path, splits it into a root and segments, then recursively resolves each segment. Symlinks are safely read via :file.read_link_all/1 and re-expanded relative to their containing directory. This process ensures that subsequent safety checks operate on absolute, fully-resolved paths rather than potentially malicious user input.
Workspace Validation
After canonicalization, Workspace.validate_workspace_path/2 (defined in elixir/lib/symphony_elixir/workspace.ex at lines 58-80) enforces the critical security constraints:
- The workspace path must not resolve to the root directory itself (workspace ≠ root)
- The workspace must start with the canonical root prefix
- If the expanded path (pre-canonicalization) attempts to escape via a symlink, it is immediately rejected
Only paths satisfying all three conditions pass validation. When validation fails, the function returns detailed error tuples such as {:workspace_outside_root, bad_path, root}, which callers propagate as {:error, ...} values.
Remote Host Security
The path safety system extends to remote SSH environments through local pre-validation. When creating workspaces on remote hosts via Workspace.create_for_issue/2 or executing remote commands through Workspace.run_remote_command/3, Symphony applies PathSafety.canonicalize/1 on the local side first.
The remote host receives only the prepared absolute path, ensuring that path-traversal vulnerabilities cannot be introduced by compromised remote scripts or malicious SSH targets. This architecture guarantees that the security boundary is enforced before any network transmission occurs.
Integration Across the Codebase
The path safety system serves as a single source of truth for workspace path handling. According to the OpenAI Symphony source code, multiple modules invoke PathSafety.canonicalize/1, ensuring that any future security enhancements propagate automatically:
elixir/lib/symphony_elixir/workspace.ex: Creates, validates, and removes per-issue workspaceselixir/lib/symphony_elixir/config/schema.ex: Validates configuration values and canonicalizes the workspace rootelixir/lib/symphony_elixir/codex/app_server.ex: Server entry point for Codex agents; uses path safety when preparing remote workspaces
Practical Code Examples
The following examples demonstrate safe workspace creation and direct path canonicalization usage:
# Example: safely create a workspace for a GitHub issue
{:ok, workspace_path} = SymphonyElixir.Workspace.create_for_issue(%{
id: 123,
identifier: "openai/symphony#123"
})
# Internally:
# 1️⃣ safe_identifier/1 sanitises the identifier → "openai_symphony_123"
# 2️⃣ workspace_path_for_issue/2 builds "<root>/openai_symphony_123"
# 3️⃣ PathSafety.canonicalize/1 resolves the absolute, symlink‑free path
# 4️⃣ validate_workspace_path/2 ensures it stays inside the root
# Direct use of the Path‑Safety module – useful for custom tooling
case SymphonyElixir.PathSafety.canonicalize("/tmp/../var/app/../sym_workspace") do
{:ok, safe_path} ->
IO.puts("Canonical path: #{safe_path}")
{:error, {:path_canonicalize_failed, original, reason}} ->
IO.warn("Failed to canonicalise #{original}: #{inspect(reason)}")
end
# Handling an error when a workspace tries to escape the root
{:error, {:workspace_outside_root, bad_path, root}} =
SymphonyElixir.Workspace.validate_workspace_path("/tmp/evil", nil)
IO.puts("Workspace #{bad_path} is outside the configured root #{root}")
Summary
- Canonicalization first: All paths are processed through
PathSafety.canonicalize/1inelixir/lib/symphony_elixir/path_safety.exto resolve symlinks and relative segments before validation. - Root containment:
Workspace.validate_workspace_path/2enforces that workspaces remain strictly within the configured root directory and never resolve to the root itself. - Remote pre-validation: Security checks execute locally before transmitting paths to remote SSH hosts, preventing traversal attacks in distributed environments.
- Unified enforcement: The system provides a single source of truth used by
Workspace,Config.Schema, andCodex.AppServermodules. - Fail-safe errors: Violations return detailed error tuples (e.g.,
{:workspace_outside_root, ...}) rather than allowing unsafe filesystem access.
Frequently Asked Questions
How does Symphony prevent symlink-based directory traversal attacks?
Symphony's path safety system prevents symlink attacks by fully resolving all symbolic links during the canonicalization phase. The PathSafety.canonicalize/1 function uses :file.read_link_all/1 to read link targets and re-expands them relative to their containing directory, ensuring the final absolute path is known before any safety checks compare it against the allowed root boundary.
What happens when a workspace path fails validation?
When Workspace.validate_workspace_path/2 detects a path outside the root directory or resolving to the root itself, it returns an error tuple such as {:workspace_outside_root, requested_path, root_path}. This error propagates through the call stack as {:error, reason}, preventing any filesystem creation, removal, or remote command execution from proceeding with the unsafe path.
Does the path safety system protect remote SSH workspaces?
Yes, the path safety system protects remote workspaces by performing all canonicalization and validation steps locally before any remote communication occurs. Functions like Workspace.create_for_issue/2 prepare the absolute path locally using PathSafety.canonicalize/1, then transmit only the validated path to the remote host. This ensures that compromised remote environments cannot influence the path resolution process or introduce traversal sequences.
Which modules depend on the PathSafety canonicalization function?
According to the OpenAI Symphony source code, PathSafety.canonicalize/1 serves as the single source of truth for multiple critical modules: SymphonyElixir.Workspace handles workspace lifecycle management, SymphonyElixir.Config.Schema validates configuration roots, and SymphonyElixir.Codex.AppServer prepares paths for Codex agent environments. This centralized design ensures consistent security enforcement across the entire application.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →