Python: Add directory allowlist configuration for SessionsPythonTool file#13467
Merged
eavanvalkenburg merged 2 commits intomicrosoft:mainfrom Jan 23, 2026
Merged
Python: Add directory allowlist configuration for SessionsPythonTool file#13467eavanvalkenburg merged 2 commits intomicrosoft:mainfrom
eavanvalkenburg merged 2 commits intomicrosoft:mainfrom
Conversation
Collaborator
Author
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request adds directory allowlist configuration for the SessionsPythonTool to provide security controls over file operations when the plugin is used with AI models.
Changes:
- Added
allowed_upload_directoriesparameter with deny-by-default behavior to restrict file uploads - Added
allowed_download_directoriesparameter with permissive-by-default behavior for optional download restrictions - Implemented path canonicalization using
os.path.realpath()to prevent path traversal attacks
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py | Adds two new configuration parameters for directory allowlists, implements path validation methods, and updates upload_file and download_file methods to enforce security restrictions |
| python/tests/unit/core_plugins/test_sessions_python_plugin.py | Updates existing tests to use real files instead of mocked file operations, adds comprehensive security tests for path validation and traversal prevention, and tests for list-to-set conversion |
Comments suppressed due to low confidence (1)
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py:369
- The upload_file method doesn't catch FileNotFoundError or other OSError exceptions that can occur when opening the file. If the file doesn't exist or can't be opened (e.g., due to permissions), the raw exception will propagate instead of being wrapped in a FunctionExecutionException with a helpful error message. Consider adding a try-except block around the file open operation to provide clearer error messages to users.
try:
with open(validated_path, "rb") as data:
files = {"file": (remote_file_path, data, "application/octet-stream")}
response = await self.http_client.post(url=url, files=files)
response.raise_for_status()
uploaded_files = await self.list_files()
return next(
file_metadata for file_metadata in uploaded_files if file_metadata.full_path == remote_file_path
)
except HTTPStatusError as e:
error_message = e.response.text if e.response.text else e.response.reason_phrase
raise FunctionExecutionException(
f"Upload failed with status code {e.response.status_code} and error: {error_message}"
) from e
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Outdated
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Outdated
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Outdated
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Outdated
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Outdated
Show resolved
Hide resolved
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Show resolved
Hide resolved
dmytrostruk
approved these changes
Jan 23, 2026
python/semantic_kernel/core_plugins/sessions_python_tool/sessions_python_plugin.py
Show resolved
Hide resolved
eavanvalkenburg
approved these changes
Jan 23, 2026
github-merge-queue bot
pushed a commit
that referenced
this pull request
Jan 23, 2026
…file (#13467) ### Motivation and Context When `SessionsPythonTool` is used with an AI model, providing explicit directory boundaries for file operations gives developers fine-grained control over which parts of the filesystem the plugin can access. This follows the pattern established by `HttpPlugin.allowed_domains`. - Add `allowed_upload_directories` parameter to control which local directories can be used for file uploads - Add `allowed_download_directories` parameter for optional restrictions on file download destinations - Implement path canonicalization to resolve symlinks and normalize paths Usage: ```python tool = SessionsPythonTool( credential=credential, allowed_upload_directories={"/app/data/uploads", "/app/user_files"}, allowed_download_directories={"/app/data/downloads"}, # optional ) ``` <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description - `upload_file` now requires `allowed_upload_directories` to be configured (deny-by-default) - `download_file` optionally supports `allowed_download_directories` (permissive-by-default, since it's not exposed as a kernel function) - Both parameters accept `set[str]` or `list[str]` for convenience - Paths are canonicalized using `os.path.realpath()` before validation <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
When
SessionsPythonToolis used with an AI model, providing explicit directory boundaries for file operations gives developers fine-grained control over which parts of the filesystem the plugin can access. This follows the pattern established byHttpPlugin.allowed_domains.allowed_upload_directoriesparameter to control which local directories can be used for file uploadsallowed_download_directoriesparameter for optional restrictions on file download destinationsUsage:
Description
upload_filenow requiresallowed_upload_directoriesto be configured (deny-by-default)download_fileoptionally supportsallowed_download_directories(permissive-by-default, since it's not exposed as a kernel function)set[str]orlist[str]for convenienceos.path.realpath()before validationContribution Checklist