Bug Description
🐛 Bug Report
Bug Description
GameCoordinator allows a remote client-controlled agent_name to flow into trajectory filenames without sanitization, enabling path traversal and file write outside ./logs/trajectories.
Relevant flow:
agent_name is taken directly from network input during join (_process_join_game_action, coordinator.py:330,337).
- The same
agent_name is later used to build a filename (_store_trajectory_to_file, coordinator.py:855) and passed to store_trajectories_to_jsonl(...).
- The helper joins
dir and filename with os.path.join(...) and writes to disk. If agent_name contains traversal segments (e.g. x/../../../../tmp/pwned), the final normalized path escapes the log directory.
Impact:
- Remote arbitrary file write (path traversal) within coordinator process permissions.
- This is exploitable whenever trajectory storage is enabled (
env.save_trajectories: true) and a reset occurs.
Steps to Reproduce
- Configure the environment with trajectory saving enabled (
env.save_trajectories: true).
- Connect as an agent and send
JoinGame with a traversal payload in agent_info.name, for example:
{"action_type":"JoinGame","parameters":{"agent_info":{"name":"x/../../../../tmp/pwned","role":"Attacker"}}}
- Trigger a reset (send
ResetGame; in single-agent mode this is sufficient).
- Observe that a file is written outside the intended log folder, e.g.
/tmp/pwned_Attacker.jsonl.
Expected Behavior
User-controlled identifiers (like agent_name) must never influence filesystem paths directly. Filenames should be sanitized/normalized (allowlist characters, strip separators, reject traversal) and writes must be constrained to the intended directory.
Version
1.1
Installation / Deployment Method
Running locally from source
Bug Description
🐛 Bug Report
Bug Description
GameCoordinatorallows a remote client-controlledagent_nameto flow into trajectory filenames without sanitization, enabling path traversal and file write outside./logs/trajectories.Relevant flow:
agent_nameis taken directly from network input during join (_process_join_game_action,coordinator.py:330,337).agent_nameis later used to build a filename (_store_trajectory_to_file,coordinator.py:855) and passed tostore_trajectories_to_jsonl(...).dirandfilenamewithos.path.join(...)and writes to disk. Ifagent_namecontains traversal segments (e.g.x/../../../../tmp/pwned), the final normalized path escapes the log directory.Impact:
env.save_trajectories: true) and a reset occurs.Steps to Reproduce
env.save_trajectories: true).JoinGamewith a traversal payload inagent_info.name, for example:{"action_type":"JoinGame","parameters":{"agent_info":{"name":"x/../../../../tmp/pwned","role":"Attacker"}}}ResetGame; in single-agent mode this is sufficient)./tmp/pwned_Attacker.jsonl.Expected Behavior
User-controlled identifiers (like
agent_name) must never influence filesystem paths directly. Filenames should be sanitized/normalized (allowlist characters, strip separators, reject traversal) and writes must be constrained to the intended directory.Version
1.1
Installation / Deployment Method
Running locally from source