Azure SDKのazure-ai-mlを使ってAzure Machine Learningの成果物やストレージ上のファイルをローカルにダウンロードしている場合、今回の更新は早めに確認すべきセキュリティ修正です。要点は、ストレージから返されたblob名やファイル名に..を含む不正なパスがあると、意図したダウンロード先ディレクトリの外へファイルを書き込む可能性があった点です。PRでは、ダウンロード先と実際の保存先を解決済みパスとして比較し、保存先の外へ出る項目をスキップして警告ログを出す修正が入っています。(GitHub)
この記事では、2026年5月5日に更新されたAzure SDK for PythonのPR「[azure-ai-ml] Fix path traversal vulnerability in storage download helpers」をもとに、何が変わったのか、どの利用者が影響を確認すべきか、移行・設定確認で見るべきポイントを実務目線で整理します。
今回のAzure SDK更新で何が変わったのか
今回の変更は、Azure SDK for Pythonのazure-ai-mlに含まれるストレージダウンロード処理に対するパストラバーサル対策です。GitHub PR #46693では、Azure Machine Learning関連の成果物ダウンロードで使われる3つのストレージヘルパーに対し、保存先パスの検証を追加しています。(GitHub)
修正対象は、次の3ファイルです。
| 対象ファイル | 対象処理 | 主な役割 |
|---|---|---|
azure/ai/ml/_artifacts/_blob_storage_helper.py | BlobStorageClient.download() | Azure Blob Storage由来のファイルをダウンロード |
azure/ai/ml/_artifacts/_gen2_storage_helper.py | Gen2StorageClient.download() | ADLS Gen2のパス一覧からファイルをダウンロード |
azure/ai/ml/_artifacts/_fileshare_storage_helper.py | recursive_download() | Azure Fileshareのファイル・ディレクトリを再帰的にダウンロード |
問題の本質は、サーバー側から返されたblob名やファイル名を使ってローカル保存パスを組み立てる際に、そのパスが本当に指定したダウンロード先ディレクトリ配下に収まるかを十分に検証していなかったことです。たとえば../../etc/maliciousのような相対パスが含まれると、OSがパスを解決した結果、指定ディレクトリの外側を指す可能性があります。PRの説明でも、このリスクはCWE-22のパストラバーサルとして整理されています。(GitHub)
パストラバーサルとは何かを実務向けに理解する
パストラバーサルは、ファイル名やパスに../などを混ぜることで、本来アクセス・書き込みすべきではない場所へ処理を誘導する脆弱性です。MITREのCWE-22では、制限されたディレクトリにパス名を適切に限定できない問題として説明され、相対パスだけでなく絶対パスを使うケースも含まれます。([CWE][2])
今回のケースで重要なのは、「ユーザーが入力したファイル名」だけが危険なのではなく、サーバーやストレージから返されるファイル名も信頼しすぎてはいけないという点です。
たとえば、アプリケーションが次のような処理をしているとします。
download_dir = "./outputs"
file_name = "../../app/config.py"
local_path = Path(download_dir, file_name)
見た目には./outputsへ保存しているように見えても、Pathが解決した最終的なパスはoutputsの外へ出る可能性があります。これがMLジョブの成果物、モデルファイル、ログ、データセット出力などのダウンロード処理で起きると、実行環境内の別ファイルを上書きするリスクにつながります。
修正のポイントは「解決済みパスが保存先配下にあるか」の確認
PRで追加された対策は、単に..という文字列を拒否するものではありません。より実務的には、保存先ディレクトリと実際に書き込もうとしているファイルのパスをPath.resolve()で解決し、そのうえでPath.relative_to()を使って、ターゲットがダウンロード先ディレクトリの配下にあるかを確認しています。(GitHub)
この考え方は、セキュリティレビューでも重要です。".."が含まれているかだけを見る実装は、OS差異、シンボリックリンク、エンコード、パス区切り文字の違いなどで抜け道が生まれやすくなります。最終的にOSが解釈するパスを解決し、許可されたルート配下に収まるかを確認するほうが安全です。
今回の修正では、不正または疑わしいパスは保存せず、警告ログを出してスキップする流れになっています。つまり、修正後は該当するファイル名が含まれていた場合に「エラーで全体停止」ではなく、「危険な項目を除外して処理継続」する挙動になる可能性があります。運用側では、この警告ログを見逃さないことが重要です。(GitHub)
影響を確認すべき利用者
今回のAzure SDK更新は、Azure SDK全体を使うすべてのユーザーが同じレベルで影響を受ける、という話ではありません。主に確認すべきなのは、Pythonのazure-ai-mlを使い、Azure Machine Learning関連の成果物やストレージ上のファイルをダウンロードしている環境です。
| 確認対象 | 対応優先度 | 理由 |
|---|---|---|
azure-ai-mlでジョブ出力、モデル、アーティファクトをローカルやCI環境へダウンロードしている | 高 | 修正対象のダウンロードヘルパーが使われる可能性がある |
| MLパイプラインやMLOpsで外部データ、共同管理ストレージ、共有Fileshareを扱う | 高 | ファイル名・ディレクトリ名を自社だけで完全管理していない可能性がある |
| Azure Machine Learningを使っているが、SDK経由のダウンロード処理はない | 中 | 直接影響は限定的でも、依存関係と運用手順の確認は必要 |
Azure SDK for Pythonを使っているが、azure-ai-mlは使っていない | 低 | 今回のPRの対象はazure-ai-ml配下のML関連ヘルパー |
| Azure Storage SDK単体のみを使って独自実装でダウンロードしている | 別途確認 | 今回の修正対象外でも、同じ種類の脆弱性を自前実装に抱える可能性がある |
特に注意したいのは、MLOps環境です。MLの成果物ダウンロードは、開発者の手元だけでなく、CI/CD、モデル評価、バッチ推論、監査用ログ収集、成果物の再配置などで自動実行されることがあります。こうした処理は一度作ると長く使われるため、依存ライブラリのバージョンが古いまま固定されていることも少なくありません。
まず確認すべきこと
最初に行うべきことは、利用中の環境でazure-ai-mlが入っているか、どのバージョンか、どの処理でダウンロードをしているかを洗い出すことです。
インストール済みバージョンを確認する
Python環境ごとに、次のコマンドで確認します。
python -m pip show azure-ai-ml
または、依存関係一覧から確認します。
python -m pip freeze | grep azure-ai-ml
Windows PowerShellの場合は次のように確認できます。
python -m pip freeze | Select-String azure-ai-ml
CI/CDやコンテナ環境では、ローカルPCだけでなく次の場所も確認してください。
| 確認場所 | 見るべきファイル・設定 |
|---|---|
| アプリケーションリポジトリ | requirements.txt、pyproject.toml、poetry.lock、Pipfile.lock |
| Dockerイメージ | Dockerfile、ベースイメージ、ビルドログ |
| CI/CD | GitHub Actions、Azure Pipelines、GitLab CIなどの依存インストール手順 |
| Azure ML環境 | Environment定義、Conda YAML、ジョブ定義、コンポーネント定義 |
| Notebook環境 | 手動インストール履歴、カーネルごとの仮想環境 |
PyPI上のazure-ai-mlはAzure Machine Learning Python SDK v2のクライアントライブラリで、MLClientを中心にジョブ、モデル、コンポーネント、エンドポイントなどを扱うパッケージです。公式のパッケージ説明でも、Azure Machine Learningワークスペースを前提に、pip install azure-ai-mlで導入する形が示されています。(PyPI)
ダウンロード処理を検索する
次に、コードベース内でダウンロード関連の処理を検索します。
grep -R "download(" -n .
grep -R "azure.ai.ml" -n .
grep -R "MLClient" -n .
検索時は、単にdownload()というメソッド名だけでは見落とすことがあります。次のような観点でも確認してください。
| 観点 | 確認例 |
|---|---|
| ジョブ出力の取得 | 学習ジョブ完了後に成果物を取得していないか |
| モデル・コンポーネントの取得 | 登録済みモデルやコンポーネントをローカルに落としていないか |
| データストア連携 | Blob、ADLS Gen2、Fileshare経由のダウンロードがないか |
| 自動処理 | 夜間バッチ、CI、評価パイプラインでダウンロードしていないか |
| 一時ディレクトリ | /tmp、作業ディレクトリ、コンテナ内の共有パスへ保存していないか |
修正版へ移行する際の判断基準
今回のPRは、確認時点でGitHub上ではAzure SDK for Pythonのmainブランチへ向けたPRとして表示されており、3コミット、3ファイル変更の内容が確認できます。PRページ上では「Open」と表示されているため、実運用では「PRの内容を見たから安全」と判断せず、利用しているazure-ai-mlのリリース版に修正が取り込まれているかを必ず確認してください。(GitHub)
実務では、次の順序で判断すると安全です。
| 手順 | やること | 判断基準 |
|---|---|---|
| 1 | 現在のazure-ai-mlバージョンを確認 | 古い固定バージョンなら更新候補 |
| 2 | 公式CHANGELOGやリリースノートを確認 | 該当修正が含まれるバージョンか |
| 3 | 検証環境でアップデート | ダウンロード処理、ジョブ実行、モデル取得が正常に動くか |
| 4 | 警告ログを確認 | resolved path is outside the destination directory系の警告が出ないか |
| 5 | 本番・共有環境へ段階展開 | CI、コンテナ、Notebook、Azure ML Environmentを揃える |
パッケージ更新の例は次のとおりです。
python -m pip install --upgrade azure-ai-ml
バージョンを固定している場合は、単純に最新版へ上げるのではなく、チームの運用ルールに合わせてrequirements.txtやロックファイルを更新します。
azure-ai-ml>=修正が含まれるバージョン
ここで重要なのは、修正バージョンを推測で書かないことです。PR段階の情報だけでは、どのリリース番号に含まれるかは断定できません。リリースノート、CHANGELOG、PyPIのリリース履歴、社内ミラーの反映状況を確認してから固定してください。
設定確認で見落としやすいポイント
今回の脆弱性はSDK内部の修正ですが、アップデートだけで終わらせると運用上のリスクが残る場合があります。特に、ダウンロード先ディレクトリの設計と権限設定は見直す価値があります。
ダウンロード先を広すぎる場所にしない
危険なのは、ダウンロード先としてアプリケーションのルート、ホームディレクトリ、共有ボリューム全体などを指定しているケースです。
避けたい例は次のような指定です。
destination = "."
destination = "/"
destination = "/home/app"
destination = "/mnt/shared"
より安全なのは、用途ごとに専用ディレクトリを作ることです。
destination = "/tmp/azureml-downloads/job-outputs"
さらに、処理完了後に不要なファイルを削除する、実行ごとにディレクトリを分ける、書き込み権限を必要最小限にする、といった対策を組み合わせると被害範囲を狭められます。
コンテナ内のマウント先に注意する
MLOpsでは、コンテナの/mntや/workspaceにホスト側ボリュームをマウントすることがあります。ダウンロード処理が意図せずマウント領域の外や重要ファイル付近に書き込める設計になっていると、SDK修正前の環境では影響が大きくなります。
確認すべき項目は次のとおりです。
| 確認項目 | 推奨される考え方 |
|---|---|
| コンテナの実行ユーザー | rootではなく専用ユーザーで実行する |
| マウント先 | ダウンロード専用のサブディレクトリに限定する |
| 書き込み権限 | 必要なディレクトリだけに付与する |
| 成果物の展開先 | アプリケーションコードや設定ファイルの場所と分ける |
| 後続処理 | ダウンロードしたファイルを無条件に実行・読み込みしない |
警告ログを監視対象に入れる
今回の修正では、保存先ディレクトリの外へ出る疑わしいパスを検出した場合にスキップし、警告ログを出す実装が追加されています。(GitHub)
そのため、アップデート後は「問題なく処理が完了したか」だけではなく、「警告が出ていないか」も確認してください。
ログ監視では、次のような文言を検索対象にするとよいでしょう。
resolved path is outside the destination directory
Skipping blob
Skipping path
Skipping file
Skipping directory
警告が出た場合、単なるSDKの挙動変更として片付けず、対象のblob名、ファイル名、ストレージアカウント、ジョブID、実行者、生成元のパイプラインを確認します。意図しない名前が生成されているだけの設定ミスか、外部入力を経由した不正なパス混入かを切り分ける必要があります。
自前のAzure Storageダウンロード処理も点検する
今回のPRはazure-ai-ml内部の修正ですが、同じ考え方は自前のダウンロード処理にも当てはまります。Azure Blob Storage、ADLS Gen2、Azure Filesからファイル一覧を取得し、名前を使ってローカルパスを組み立てているコードがある場合は、同様のパストラバーサル対策が必要です。
危険な実装例です。
from pathlib import Path
def save_file(destination, remote_name, content):
local_path = Path(destination, remote_name)
local_path.parent.mkdir(parents=True, exist_ok=True)
local_path.write_bytes(content)
このコードは、remote_nameが安全であることを前提にしています。../や絶対パス、想定外の区切り文字が混じると、保存先の外へ書き込むリスクがあります。
改善例は次のようになります。
from pathlib import Path
def safe_save_file(destination, remote_name, content):
base_dir = Path(destination).resolve()
target_path = Path(destination, remote_name).resolve()
try:
target_path.relative_to(base_dir)
except ValueError:
raise ValueError(f"Unsafe path detected: {remote_name}")
target_path.parent.mkdir(parents=True, exist_ok=True)
target_path.write_bytes(content)
ポイントは、文字列として".."を探すだけではなく、解決済みのパスが許可したディレクトリ配下にあるかを確認することです。これは今回のPRで採用されている考え方とも一致します。(GitHub)
対応時に起きやすい失敗
「Azure SDKを使っているから安全」と判断してしまう
Azure SDKを使っていても、すべての処理が自動的に安全になるわけではありません。SDK内部の修正対象になった処理は改善されますが、アプリケーション側で独自にファイルパスを作っている部分は別です。
特に、次のような処理は個別にレビューしてください。
- blob名をそのままファイル名として保存する
- zipやtarなどのアーカイブを展開する
- 外部データセットのファイル名をそのまま使う
- MLジョブ出力を別ディレクトリへコピーする
- ダウンロード後のファイルを自動実行・自動インポートする
Notebookだけ更新して本番環境を忘れる
Azure Machine Learningの利用では、Notebook、ローカルPC、CI、Azure ML Environment、推論用コンテナなど、複数のPython環境が存在しがちです。Notebookでpip install --upgrade azure-ai-mlを実行しても、本番ジョブのコンテナやCIの依存関係は変わりません。
対応時は、環境ごとにバージョンを確認してください。
| 環境 | よくある見落とし |
|---|---|
| ローカル開発環境 | 開発者ごとにバージョンが違う |
| Notebook | カーネル再起動前の古いパッケージが使われる |
| CI/CD | キャッシュされた依存パッケージが使われる |
| Docker | ベースイメージ内の古いライブラリが残る |
| Azure ML Environment | 登録済み環境の再ビルドを忘れる |
修正後のスキップ挙動を「欠損」と誤解する
修正後に疑わしいパスがスキップされると、これまで存在していたファイルがダウンロードされないように見える可能性があります。しかし、そのファイル名が保存先ディレクトリの外を指すなら、スキップは安全のための正しい挙動です。
この場合は、ファイルを無理に取得するのではなく、ストレージ上のファイル名や生成元の処理を修正してください。
実務での対応チェックリスト
今回のAzure SDK更新を受けて、チームで実施すべき確認をチェックリストにまとめます。
| チェック項目 | 対応状況 |
|---|---|
azure-ai-mlを利用している環境を洗い出した | |
| SDK経由で成果物・モデル・ジョブ出力・ストレージファイルをダウンロードしている箇所を確認した | |
| GitHub PR、CHANGELOG、リリースノートで修正取り込み状況を確認した | |
| 修正が含まれるバージョンへアップデートする計画を立てた | |
| 検証環境で既存のMLジョブ、成果物取得、モデル取得が動くことを確認した | |
警告ログにresolved path is outside the destination directory系の出力がないか確認した | |
| ダウンロード先ディレクトリを専用化し、広すぎる保存先を避けた | |
| コンテナやCIの依存関係も更新した | |
| 自前のStorageダウンロード処理にも同様のパス検証を入れた | |
| チームのセキュリティレビュー項目に「外部由来ファイル名のパス検証」を追加した |
まとめ:アップデート確認とダウンロード先の見直しをセットで行う
今回のAzure SDK for Pythonのazure-ai-ml更新は、Azure Machine LearningのストレージダウンロードヘルパーにおけるCWE-22パストラバーサル対策です。修正内容は、保存先ディレクトリと実際のターゲットパスを解決したうえで、ターゲットが保存先配下に収まるかを確認し、外へ出るパスをスキップするものです。(GitHub)
対応の優先度が高いのは、azure-ai-mlを使ってAzure Machine Learningのジョブ出力、モデル、コンポーネント、データストア上のファイルをローカル・コンテナ・CI環境へダウンロードしているチームです。
次に取るべき行動は明確です。まず利用中のazure-ai-mlバージョンとダウンロード処理を洗い出し、修正が含まれるリリースへの更新可否を確認してください。そのうえで、ダウンロード先を専用ディレクトリに限定し、警告ログを監視し、自前のStorageダウンロード処理にも同じパス検証を入れることが重要です。SDKのアップデートだけで終わらせず、ML成果物を安全に扱う運用設計まで見直すことで、今回の変更を実務上のリスク低減につなげられます。
[2]: https://cwe.mitre.org/data/definitions/22.html “CWE –
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') (4.20)
"

コメント