fix(agents): validate the agent name in FileAgentStore.get_soul (#7265)

get_soul was the only read/write method that skipped validate_agent_name,
so a name like "../../other-user/agents/planner" reached
resolve_agent_dir and read another user's SOUL.md. Validate it like the
other methods do.

The regression test asserts ValueError for a traversal name; it reads the
other user's soul on main.

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
Huang-404-Q 2026-10-23 14:54:21 +08:00 committed by GitHub
parent cc013c9680
commit 5839822aa1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 10 additions and 0 deletions

View File

@ -64,6 +64,9 @@ class FileAgentStore(AgentStore):
return paths.user_agent_dir(effective_user, name).exists() or paths.agent_dir(name).exists()
def get_soul(self, name: str, *, user_id: str | None = None) -> str | None:
# Every other read/write method validates the name; without this, a
# ".." segment reaches resolve_agent_dir and escapes the user's tree.
name = validate_agent_name(name)
agent_dir = resolve_agent_dir(name, user_id=user_id)
soul_path = agent_dir / SOUL_FILENAME
# resolve_agent_dir requires config.yaml; SOUL.md loading does not, so

View File

@ -426,3 +426,10 @@ def test_get_agent_store_does_not_fallback_when_extensions_config_is_missing(tmp
finally:
reset_app_config()
reset_extensions_config()
def test_file_get_soul_rejects_path_traversal(file_home):
store = FileAgentStore()
with pytest.raises(ValueError, match="Invalid agent name"):
store.get_soul("../../u2/agents/planner", user_id="u1")