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:

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/1 in elixir/lib/symphony_elixir/path_safety.ex to resolve symlinks and relative segments before validation.
  • Root containment: Workspace.validate_workspace_path/2 enforces 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, and Codex.AppServer modules.
  • Fail-safe errors: Violations return detailed error tuples (e.g., {:workspace_outside_root, ...}) rather than allowing unsafe filesystem access.

Frequently Asked Questions

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →