diff --git a/.github/workflows/update.yaml b/.github/workflows/update.yaml new file mode 100644 index 000000000000..9630bbec5cde --- /dev/null +++ b/.github/workflows/update.yaml @@ -0,0 +1,31 @@ +name: Update to Upstream + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: "*/30 * * * *" + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: configure + run: | + git config --global user.name 'Robot' + git config --global user.email 'robot@oreply.github.com' + # "git checkout main" is unnecessary, already here by default + git pull --unshallow # this option is very important, you would get + # complains about unrelated histories without it. + # (but actions/checkout@v2 can also be instructed + # to fetch all git depth right from the start) + git remote add upstream https://fuchsia.googlesource.com/fuchsia/ + git fetch upstream + + git checkout main + git rebase upstream/main && git push -f origin main diff --git a/scripts/sdk/common/frontend.py b/scripts/sdk/common/frontend.py index 80f8fe254a1f..41973270472c 100644 --- a/scripts/sdk/common/frontend.py +++ b/scripts/sdk/common/frontend.py @@ -262,7 +262,26 @@ def _create_archive_dir(self): # This is vastly more efficient than accessing files one by one via # the tarfile API. with tarfile.open(self._archive) as archive: - archive.extractall(temp_dir) + def is_within_directory(directory, target): + + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + + return prefix == abs_directory + + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): + + for member in tar.getmembers(): + member_path = os.path.join(path, member.name) + if not is_within_directory(path, member_path): + raise Exception("Attempted Path Traversal in Tar File") + + tar.extractall(path, members, numeric_owner=numeric_owner) + + + safe_extract(archive, temp_dir) try: yield temp_dir finally: diff --git a/scripts/sdk/merger/merge.py b/scripts/sdk/merger/merge.py index c0632818a7c8..e1d0b1d742d4 100755 --- a/scripts/sdk/merger/merge.py +++ b/scripts/sdk/merger/merge.py @@ -371,7 +371,26 @@ def open_archive(self, archive: Path) -> Path: """Uncompress an archive and return the path of its temporary extraction directory.""" extract_dir = self.get_temp_dir() with tarfile.open(archive) as archive_file: - archive_file.extractall(extract_dir) + def is_within_directory(directory, target): + + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + + return prefix == abs_directory + + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): + + for member in tar.getmembers(): + member_path = os.path.join(path, member.name) + if not is_within_directory(path, member_path): + raise Exception("Attempted Path Traversal in Tar File") + + tar.extractall(path, members, numeric_owner=numeric_owner) + + + safe_extract(archive_file, extract_dir) return extract_dir def write_archive(self, archive: Path, source_dir: Path):