Skip to content

Commit 22f2584

Browse files
committed
[sec]Adding validation for resolved path to deny sensitive directories
1 parent 4055fcf commit 22f2584

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

sagemaker-core/src/sagemaker/core/common_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
WAITING_DOT_NUMBER = 10
7575
MAX_ITEMS = 100
7676
PAGE_SIZE = 10
77+
SENSITIVE_SYSTEM_ROOTS = ["/", "/etc", "/var"]
7778

7879
logger = logging.getLogger(__name__)
7980

@@ -612,6 +613,9 @@ def _create_or_update_code_dir(
612613
):
613614
"""Placeholder docstring"""
614615
code_dir = os.path.join(model_dir, "code")
616+
resolved_code_dir = _get_resolved_path(code_dir)
617+
if resolved_code_dir in SENSITIVE_SYSTEM_ROOTS:
618+
raise ValueError(f"Invalid code_dir path: {code_dir} resolves to sensitive system root {resolved_code_dir}")
615619
if source_directory and source_directory.lower().startswith("s3://"):
616620
local_code_path = os.path.join(tmp, "local_code.tar.gz")
617621
download_file_from_url(source_directory, local_code_path, sagemaker_session)

sagemaker-core/tests/unit/test_common_utils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,3 +2209,43 @@ def test_nested_set_dict_multiple_keys(self):
22092209
d = {}
22102210
nested_set_dict(d, ["a", "b", "c"], "value")
22112211
assert d["a"]["b"]["c"] == "value"
2212+
2213+
2214+
class TestCreateOrUpdateCodeDir:
2215+
"""Test _create_or_update_code_dir function."""
2216+
2217+
def test_create_or_update_code_dir_rejects_root(self, tmp_path):
2218+
"""Test that root path is rejected."""
2219+
from sagemaker.core.common_utils import _create_or_update_code_dir
2220+
2221+
with patch("sagemaker.core.common_utils._get_resolved_path", return_value="/"):
2222+
with pytest.raises(ValueError, match="sensitive system root"):
2223+
_create_or_update_code_dir("/", "script.py", None, [], Mock(), str(tmp_path))
2224+
2225+
def test_create_or_update_code_dir_rejects_etc(self, tmp_path):
2226+
"""Test that /etc path is rejected."""
2227+
from sagemaker.core.common_utils import _create_or_update_code_dir
2228+
2229+
with patch("sagemaker.core.common_utils._get_resolved_path", return_value="/etc"):
2230+
with pytest.raises(ValueError, match="sensitive system root"):
2231+
_create_or_update_code_dir("/etc", "script.py", None, [], Mock(), str(tmp_path))
2232+
2233+
def test_create_or_update_code_dir_rejects_var(self, tmp_path):
2234+
"""Test that /var path is rejected."""
2235+
from sagemaker.core.common_utils import _create_or_update_code_dir
2236+
2237+
with patch("sagemaker.core.common_utils._get_resolved_path", return_value="/var"):
2238+
with pytest.raises(ValueError, match="sensitive system root"):
2239+
_create_or_update_code_dir("/var", "script.py", None, [], Mock(), str(tmp_path))
2240+
2241+
def test_create_or_update_code_dir_allows_safe_path(self, tmp_path):
2242+
"""Test that safe paths are allowed."""
2243+
from sagemaker.core.common_utils import _create_or_update_code_dir
2244+
2245+
model_dir = tmp_path / "model"
2246+
model_dir.mkdir()
2247+
script = tmp_path / "script.py"
2248+
script.write_text("# script")
2249+
2250+
_create_or_update_code_dir(str(model_dir), str(script), None, [], Mock(), str(tmp_path))
2251+
assert (model_dir / "code").exists()

0 commit comments

Comments
 (0)