@@ -16,6 +16,19 @@ class AgentLoader:
1616 def __init__ (self , model_registry : Optional [Dict [str , BaseLLM ]] = None ):
1717 self .model_registry = model_registry or {}
1818 self .tool_registry : Dict [str , BaseTool ] = {}
19+ self ._base_dir = Path .cwd ().resolve ()
20+
21+ def _resolve_safe_path (self , path : str ) -> Path :
22+ """Resolve and validate path stays under the loader base directory."""
23+ candidate = Path (path ).expanduser ()
24+ resolved = candidate .resolve ()
25+ try :
26+ resolved .relative_to (self ._base_dir )
27+ except ValueError as e :
28+ raise ValueError (
29+ f"Path traversal detected. '{ path } ' escapes base directory '{ self ._base_dir } '."
30+ ) from e
31+ return resolved
1932
2033 def register_model (self , name : str , model : BaseLLM ) -> None :
2134 """Register a model for use in agents."""
@@ -32,23 +45,27 @@ def load_agent(
3245 tools : Optional [List [BaseTool ]] = None
3346 ) -> Agent :
3447 """Load an agent from a configuration file."""
48+ safe_config_path = self ._resolve_safe_path (config_path )
49+ if safe_config_path .suffix .lower () != ".json" :
50+ raise ValueError (f"Agent config must be a JSON file: { config_path } " )
51+
3552 # Load config
3653 try :
37- with open (config_path , "r" , encoding = "utf-8" ) as f :
54+ with open (safe_config_path , "r" , encoding = "utf-8" ) as f :
3855 config = json .load (f )
3956 except FileNotFoundError as e :
40- raise FileNotFoundError (f"Agent config file not found: { config_path } " ) from e
57+ raise FileNotFoundError (f"Agent config file not found: { safe_config_path } " ) from e
4158 except json .JSONDecodeError as e :
4259 raise ValueError (
43- f"Invalid JSON in agent config file: { config_path } . { e } "
60+ f"Invalid JSON in agent config file: { safe_config_path } . { e } "
4461 ) from e
4562 except OSError as e :
4663 raise RuntimeError (
47- f"Failed to read agent config file: { config_path } . { e } "
64+ f"Failed to read agent config file: { safe_config_path } . { e } "
4865 ) from e
4966
5067 if not isinstance (config , dict ):
51- raise ValueError (f"Agent config must be a JSON object: { config_path } " )
68+ raise ValueError (f"Agent config must be a JSON object: { safe_config_path } " )
5269
5370 # Validate config
5471 required_keys = {"model" , "system_prompt" }
@@ -93,7 +110,9 @@ def load_agents_from_dir(
93110 ) -> Dict [str , Agent ]:
94111 """Load multiple agents from a directory of config files."""
95112 agents = {}
96- config_dir = Path (dir_path )
113+ config_dir = self ._resolve_safe_path (dir_path )
114+ if not config_dir .is_dir ():
115+ raise FileNotFoundError (f"Agent config directory not found: { config_dir } " )
97116
98117 for config_file in config_dir .glob ("*.json" ):
99118 agent_name = config_file .stem
0 commit comments