Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions monai/auto3dseg/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,14 @@ def algo_from_json(filename: str, template_path: PathLike | None = None, **kwarg
if state_template_path:
algo_config["template_path"] = state_template_path

warnings.warn(
Comment thread
ericspod marked this conversation as resolved.
f"loading {filename}: the file's `_target_` value is resolved to an importable callable and "
Comment thread
ericspod marked this conversation as resolved.
Outdated
"invoked, and template directories from the file may be added to `sys.path`; only load "
"algo_object.json files from a source you trust "
"(see https://github.com/Project-MONAI/MONAI/security/advisories/GHSA-2wx3-8x3w-r8qv).",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
stacklevel=2,
)

parser = ConfigParser(algo_config)
algo = parser.get_parsed_content()
used_template_path = path
Expand Down
32 changes: 32 additions & 0 deletions tests/apps/test_auto3dseg.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@

from __future__ import annotations

import json
import os
import tempfile
import unittest
import warnings
from copy import deepcopy
from numbers import Number

Expand All @@ -36,6 +38,7 @@
SampleOperations,
SegSummarizer,
SummaryOperations,
algo_from_json,
datafold_read,
verify_report_format,
)
Expand Down Expand Up @@ -177,6 +180,20 @@ def __call__(self, data):
return d


class _DummyAlgo:
"""Minimal stand-in for an Auto3DSeg Algo object used in warning tests."""

def __init__(self) -> None:
self.template_path: str | None = None
self.output_path = os.getcwd()

def load_state_dict(self, state: dict) -> None:
pass

def get_output_path(self) -> str:
return self.output_path


class TestDataAnalyzer(unittest.TestCase):
def setUp(self):
self.test_dir = tempfile.TemporaryDirectory()
Expand Down Expand Up @@ -619,5 +636,20 @@ def tearDown(self) -> None:
self.test_dir.cleanup()


class TestAlgoFromJsonSecurityWarning(unittest.TestCase):
def test_warns_about_untrusted_target(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
algo_file = os.path.join(tmpdir, "algo_object.json")
with open(algo_file, "w", encoding="utf-8") as f:
json.dump({"_target_": f"{__name__}._DummyAlgo"}, f)

with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
algo_from_json(algo_file)

messages = [str(w.message) for w in caught]
assert any("algo_object.json" in msg and "trust" in msg for msg in messages), messages
Comment thread
ericspod marked this conversation as resolved.
Outdated


if __name__ == "__main__":
unittest.main()
Loading