Skip to content

contain JobOperations.download output paths within download_path#47834

Open
nabhan06 wants to merge 1 commit into
Azure:mainfrom
nabhan06:job-download-path-traversal
Open

contain JobOperations.download output paths within download_path#47834
nabhan06 wants to merge 1 commit into
Azure:mainfrom
nabhan06:job-download-path-traversal

Conversation

@nabhan06

@nabhan06 nabhan06 commented Jul 4, 2026

Copy link
Copy Markdown

Description

JobOperations.download builds each output's local destination as download_path / "named-outputs" / item_name, where item_name is a job output name taken verbatim from the run-history service response (get_job_output_uris_from_dataplane -> run_metadata.outputs keys). A name containing .. climbs out of download_path, and an absolute name makes pathlib drop download_path entirely, so artifacts land in a directory the job author picked rather than the one the caller asked for. The blob/gen2/fileshare helpers already contain each blob relative to their destination, but that check runs against the already-escaped destination, so it can't stop this. The download loop now resolves each destination and skips any output whose path would fall outside download_path.

Added a unit test in test_job_operations.py that returns malicious output names from the service and asserts nothing is written outside download_path.

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

Copilot AI review requested due to automatic review settings July 4, 2026 09:22
@github-actions github-actions Bot added Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. Machine Learning labels Jul 4, 2026
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution @nabhan06! We will review the pull request and get back to you soon.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a path-traversal vulnerability in JobOperations.download (sdk/ml/azure-ai-ml). Output names are taken verbatim from the run-history service response and used to build local destinations as download_path / "named-outputs" / item_name. A name containing .. segments or an absolute path could cause pathlib to place artifacts outside the caller-supplied download_path. The fix resolves each destination and skips any output that would fall outside download_path, and adds a unit test asserting malicious output names are not written outside the download directory.

Changes:

  • Added a containment check in the download loop that resolves the destination and skips (with a warning) any output whose resolved path escapes download_path.
  • Added test_download_skips_output_name_path_traversal verifying ..-based and absolute output names are skipped while the legitimate default/logs output is still downloaded.
  • Added a CHANGELOG entry under the 1.35.0 (unreleased) Bugs Fixed section.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
sdk/ml/azure-ai-ml/azure/ai/ml/operations/_job_operations.py Adds resolve-and-contain check so outputs resolving outside download_path are skipped instead of escaping the directory.
sdk/ml/azure-ai-ml/tests/job_common/unittests/test_job_operations.py New unit test returning malicious output names and asserting nothing is written outside download_path.
sdk/ml/azure-ai-ml/CHANGELOG.md Documents the bug fix under 1.35.0 (unreleased) Bugs Fixed.

The fix is correct and well-targeted: download_path is normalized to a Path earlier in the method (line 994), the containment check uses resolve() on both sides (correctly collapsing .. and normalizing absolute overrides and symlinks), and the batch/default branches are not vulnerable since they use fixed directory names rather than the untrusted item_name. The test's mocked status (JobStatus.COMPLETED) is a valid terminal status, the mocks bypass unrelated code paths correctly, and the assertions cover both the traversal and absolute-path cases plus the legitimate download. No async duplicate of this logic exists that would need the same change.

@nabhan06

nabhan06 commented Jul 9, 2026

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. Machine Learning

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants