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 14, 2025
1 parent f7064c7 commit 1438a31
Show file tree
Hide file tree
Showing 4 changed files with 38 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
4 changes: 3 additions & 1 deletion atomic_reactor/utils/cachi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import logging

import sys
from typing import Any, Callable, Dict, Optional, Tuple, List
from pathlib import Path
import os.path
Expand All @@ -23,11 +24,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
25 changes: 25 additions & 0 deletions tests/plugins/test_cachi2_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,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 +371,30 @@ def test_dependency_replacements(workflow):
expect_error="Dependency replacements are not supported by Cachi2")


def test_enforce_sandbox(workflow, mocked_cachi2_init, tmp_path):
"""Should remove symlink pointing outside of repository"""
container_yaml_config = dedent("""\
remote_source:
repo: https://git.example.com/team/repo.git
ref: a55c00f45ec3dfee0c766cea3d395d6e21cc2e5a
packages:
gomod:
- path: "."
remove_unsafe_symlinks: True
""")
mock_repo_config(workflow, data=container_yaml_config)

write_file_tree({"subdir": {"symlink_to_root": Symlink("/")}}, tmp_path)

msg = (
"Removing..."
)
with pytest.raises(ValueError):
mocked_cachi2_init(workflow).run()

# assert msg in str(exc_info)


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 1438a31

Please sign in to comment.