Repository navigation
Conversation
There was a problem hiding this comment.
🤖 AI code review
This PR hardens local-code packaging in ModelBuilder.build()/repack_model/tar_and_upload_dir by rejecting nested symlinks that resolve outside the input directory, and tightens the existing sensitive-path denylist (whole-component matching via commonpath, symlink-resolved denylist forms, adding /proc, /sys, /dev). create_tar_file is intentionally left unchanged for model-artifact uploads. The change is well-aligned with prior packaging-side symlink hardening (Source: #5906) and comes with thorough unit tests covering in-root/out-of-root, relative, and symlinked-root cases. I found no correctness, security, or test-coverage issues; the implementation and tests look solid.
Reviewed commit 9c65e35. Automated review; verify before acting.
Summary
When
ModelBuilder.build()packages local code,repack_modelcopiessource_dir, dependencies, and the inference script into the model archive, andtar_and_upload_dirarchives them directly. Both follow nested symlinks, so a symlink inside one of these inputs that points elsewhere on the file system gets packaged as a regular file. This change checks that nested symlinks resolve inside the input they belong to before packaging. It also tightens the path checks those inputs already go through.Changes
sagemaker-core/src/sagemaker/core/common_utils.py_validate_symlinks_within_root(), which walks a directory and raisesValueErrorif a nested file or directory symlink resolves outside it. Symlinks that resolve inside the directory, relative or absolute, are still supported._create_or_update_code_dirruns this check onsource_directoryand on each dependency before copying, and now applies the existing path validation toinference_script.source_directory, dependencies, the inference script, andcode_dir:/etcis/private/etcon macOS)os.path.commonpathinstead of a string prefix/proc,/sys, and/devto the restricted pathssagemaker-core/src/sagemaker/core/fw_utils.pytar_and_upload_dirruns the same symlink check ondirectory(orscriptwhen no directory is given) and on each dependency before creating the archive.create_tar_fileis unchanged. It is shared with model artifact uploads, where symlinks outside the source root are expected (for example, Hugging Face cache snapshots that link into../../blobs).Behavior change
A symlink under
source_diror a dependency directory that resolves outside that directory now raisesValueErrorduring packaging. To fix this, copy the target into the directory, or pointsource_dirat a parent directory that contains both. S3source_dirinputs are not affected.Testing
sagemaker-core/tests/unit/test_common_utils.pycover:source_dir, dependency directories, andinference_scriptin_create_or_update_code_dirrepack_modelwith localfile://URIs/etcafter resolution,/proc,/sys,/dev, and component-level matchingcreate_tar_filestill following symlinks for model uploadstar_and_upload_dirtests insagemaker-core/tests/unit/test_fw_utils.pycover rejection forsource_dir, dependencies, and directory entry points, and packaging of in-root symlinks.test_common_utils.pyandtest_fw_utils.pypass, as dosagemaker-servetest_model_builder_build.pyand thesagemaker-mlopsworkflow repack/model-step tests.