fix: enforce path boundary in built-in agent file tools and restrict YAML callback invocation#5413
Conversation
…YAML callback invocation resolve_root_directory.py: - Add _validate_root_directory() to reject absolute paths and '..' in session-state-supplied root_directory (mirrors cbcb5e6 for file_artifact_service) - Enforce project root boundary in resolve_file_path() via .relative_to() for both absolute and relative input paths config_agent_utils.py: - Restrict resolve_code_reference() to only invoke callables with args when the resolved object is a class constructor (inspect.isclass()). Plain functions and built-ins (e.g. os.system) cannot be called with args from YAML config.
|
Hi @adilburaksen , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Please fix formatting errors by running autoformat.sh |
|
Fixed — ran |
|
Hi @rohityan — happy to provide any additional context.
Both issues are triggered through agent config loading or session state manipulation. Let me know if you'd like a more detailed write-up or additional test coverage for specific scenarios. |
Fixes pyink formatting check failure requested by reviewer.
f5ecc81 to
629925f
Compare
Summary
This PR fixes two security issues in the Agent Builder Assistant's file tools and YAML agent config loading.
Fix 1 — Path boundary enforcement in
resolve_file_path()(resolve_root_directory.py)Issue:
resolve_file_path()accepted absolute paths without checking whether they were within the project root, and trustedroot_directoryfrom session state without validation. This allowed file operations outside the intended project directory.Fix:
_validate_root_directory()that rejects absolute paths, null bytes, backslashes, and..components in session-state-suppliedroot_directory(mirrors the same pattern applied in commitcbcb5e6forfile_artifact_service.py).relative_to()for both absolute and relative inputsFix 2 — Restrict callable invocation in
resolve_code_reference()(config_agent_utils.py)Issue:
resolve_code_reference()called any Python callable with attacker-supplied args from YAML config at deserialization time. This allowed specifying dangerous built-ins (e.g.os.system) as callbacks with arbitrary arguments.Fix: Only invoke a callable with
argswhen the resolved object is a class constructor (inspect.isclass()). Plain functions cannot be called with args from YAML config; they are returned as references for the framework to invoke at the appropriate time.Testing
Both fixes are verified with unit tests confirming:
root_directory: "/"injection is blockedos.systemand other non-class callables with args are blocked in YAML config