Skip to content

Commit

Permalink
feat(utils): implement remove-unsafe-symlinks flag for cachi2
Browse files Browse the repository at this point in the history
What/why:

implement parsing `remove-unsafe-symlinks` flag, which toggles
removing all symlinks which point to location(s) outside of any cloned
repository (default `False`)

How:

 - parse flag `remove-unsafe-symlinks` from "remote-source" section of   'container.yaml'

Signed-off-by: Ben Alkov <ben.alkov@redhat.com>
  • Loading branch information
ben-alkov committed Jan 22, 2025
1 parent 0f26fe2 commit d766c1a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 3 deletions.
10 changes: 9 additions & 1 deletion atomic_reactor/plugins/cachi2_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,15 @@ def process_remote_sources(self) -> List[Dict[str, Any]]:
remote_source_data["ref"]
)

enforce_sandbox(source_path_app, remove_unsafe_symlinks=False)
remove_unsafe_symlinks = False
flags = remote_source_data.get("flags", [])
if "remove-unsafe-symlinks" in flags:
remove_unsafe_symlinks = True

enforce_sandbox(
source_path_app,
remove_unsafe_symlinks,
)
validate_paths(source_path_app, remote_source_data.get("packages", {}))

if clone_only(remote_source_data):
Expand Down
3 changes: 2 additions & 1 deletion atomic_reactor/utils/cachi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ class SymlinkSandboxError(Exception):
"""Found symlink(s) pointing outside the sandbox."""


def enforce_sandbox(repo_root: Path, remove_unsafe_symlinks: bool) -> None:
def enforce_sandbox(repo_root: Path, remove_unsafe_symlinks: bool = False) -> None:
"""
Check that there are no symlinks that try to leave the cloned repository.
:param (str | Path) repo_root: absolute path to root of cloned repository
:param bool remove_unsafe_symlinks: remove unsafe symlinks if any are found
:raises OsbsValidationException: if any symlink points outside of cloned repository
"""
for path_to_dir, subdirs, files in os.walk(repo_root):
Expand Down
31 changes: 31 additions & 0 deletions tests/plugins/test_cachi2_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
of the BSD license. See the LICENSE file for details.
"""

from pathlib import Path
from textwrap import dedent
import os.path
import json
Expand Down Expand Up @@ -35,6 +36,7 @@
from tests.mock_env import MockEnv

from tests.stubs import StubSource
from tests.utils.test_cachi2 import Symlink, write_file_tree


REMOTE_SOURCE_REPO = 'https://git.example.com/team/repo.git'
Expand Down Expand Up @@ -370,6 +372,35 @@ def test_dependency_replacements(workflow):
expect_error="Dependency replacements are not supported by Cachi2")


def test_enforce_sandbox(workflow: DockerBuildWorkflow) -> None:
"""Should remove symlink pointing outside of repository"""
container_yaml_config = dedent(f"""\
remote_source:
flags:
- remove-unsafe-symlinks
repo: {REMOTE_SOURCE_REPO}
ref: {REMOTE_SOURCE_REF}
pkg_managers: []
""")

mock_repo_config(workflow, data=container_yaml_config)

def clone_f(repo, target_dir, ref):
bad_symlink = Path(target_dir / 'symlink_to_root')
with open(target_dir / "clone.txt", "w") as f:
f.write(f"{repo}:{ref}")
f.flush()
write_file_tree({bad_symlink: Symlink("/")}, target_dir)
assert Path(target_dir / bad_symlink).exists()

mocked = flexmock(Cachi2InitPlugin)
mocked.should_receive('clone_remote_source').replace_with(clone_f)
Cachi2InitPlugin(workflow).run()

assert not Path(workflow.build_dir.path / CACHI2_BUILD_DIR / "remote-source"
/ CACHI2_BUILD_APP_DIR / "symlink_to_root").exists()


def run_plugin_with_args(workflow, dependency_replacements=None, expect_error=None,
expect_result=True, expected_plugin_results=None):
runner = (MockEnv(workflow)
Expand Down
2 changes: 1 addition & 1 deletion tests/utils/test_cachi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def test_remote_source_invalid_paths(tmpdir, remote_source_packages, expected_er


def test_remote_source_path_to_symlink_out_of_repo(tmpdir):
"""If cloned repo contains symlink that points out fo repo,
"""If cloned repo contains symlink that points out of repo,
path in packages shouldn't be allowed"""
tmpdir_path = Path(tmpdir)

Expand Down

0 comments on commit d766c1a

Please sign in to comment.