Beispiel #1
0
    def _push_new_ranges_and_versions(self, source_repo, repo, vulnerability,
                                      yaml_path, original_sha256,
                                      range_collectors, versions):
        """Pushes new ranges and versions."""
        old_ranges = list(vulnerability.affects.ranges)
        del vulnerability.affects.ranges[:]

        for repo_url, range_collector in range_collectors.items():
            for introduced, fixed in range_collector.ranges():
                vulnerability.affects.ranges.add(
                    type=vulnerability_pb2.AffectedRange.Type.GIT,
                    repo=repo_url,
                    introduced=introduced,
                    fixed=fixed)

        has_changes = old_ranges != list(vulnerability.affects.ranges)
        for version in sorted(versions):
            if version not in vulnerability.affects.versions:
                has_changes = True
                vulnerability.affects.versions.append(version)

        if not has_changes:
            return True

        # Write updates, and push.
        vulnerability.modified.FromDatetime(osv.utcnow())
        osv.vulnerability_to_yaml(vulnerability, yaml_path)
        repo.index.add_all()
        return osv.push_source_changes(repo,
                                       f'Update {vulnerability.id}',
                                       self._git_callbacks(source_repo),
                                       expected_hashes={
                                           yaml_path: original_sha256,
                                       })
Beispiel #2
0
    def _push_new_ranges_and_versions(self, source_repo, repo, vulnerability,
                                      yaml_path, original_sha256,
                                      range_collectors, versions):
        """Pushes new ranges and versions."""
        has_changes = False

        for repo_url, range_collector in range_collectors.items():
            for introduced, fixed in range_collector.ranges():
                if any(
                        # Range collectors use None, while the proto uses '' for empty
                        # values.
                    (affected_range.introduced or None) == introduced and (
                        affected_range.fixed or None) == fixed
                        for affected_range in vulnerability.affects.ranges):
                    # Range already exists.
                    continue

                has_changes = True
                vulnerability.affects.ranges.add(
                    type=vulnerability_pb2.AffectedRange.Type.GIT,
                    repo=repo_url,
                    introduced=introduced,
                    fixed=fixed)

        for version in sorted(versions):
            if version not in vulnerability.affects.versions:
                has_changes = True
                vulnerability.affects.versions.append(version)

        if not has_changes:
            return True

        # Write updates, and push.
        vulnerability.modified.FromDatetime(osv.utcnow())
        osv.vulnerability_to_yaml(vulnerability, yaml_path)
        repo.index.add_all()
        return osv.push_source_changes(repo,
                                       f'Update {vulnerability.id}',
                                       self._git_callbacks(source_repo),
                                       expected_hashes={
                                           yaml_path: original_sha256,
                                       })
Beispiel #3
0
    def _push_new_ranges_and_versions(self, source_repo, repo, vulnerability,
                                      yaml_path, added_ranges, added_versions):
        # Add new ranges and versions (sorted for determinism).
        for repo_url, introduced, fixed in sorted(added_ranges):
            vulnerability.affects.ranges.add(
                type=vulnerability_pb2.AffectedRangeNew.Type.GIT,
                repo=repo_url,
                introduced=introduced,
                fixed=fixed)

        for version in sorted(added_versions):
            vulnerability.affects.versions.append(version)

        # Write updates, and push.
        vulnerability.last_modified.FromDatetime(osv.utcnow())
        osv.vulnerability_to_yaml(vulnerability, yaml_path)
        # TODO(ochang): Hash check for conflicts.
        repo.index.add_all()
        return osv.push_source_changes(repo, f'Update {vulnerability.id}',
                                       self._git_callbacks(source_repo))
Beispiel #4
0
    def import_new_oss_fuzz_entries(self, repo, oss_fuzz_source):
        """Import new entries."""
        exported = []
        vulnerabilities_path = os.path.join(
            osv.repo_path(repo), oss_fuzz_source.directory_path or '')
        for bug in osv.Bug.query(
                osv.Bug.source_of_truth == osv.SourceOfTruth.INTERNAL):
            if bug.status != osv.BugStatus.PROCESSED:
                continue

            if not bug.public:
                continue

            source_name, _ = osv.parse_source_id(bug.source_id)
            if source_name != oss_fuzz_source.name:
                continue

            vulnerability_path = os.path.join(vulnerabilities_path,
                                              osv.source_path(bug))
            os.makedirs(os.path.dirname(vulnerability_path), exist_ok=True)
            if os.path.exists(vulnerability_path):
                continue

            logging.info('Writing %s', bug.key.id())
            osv.vulnerability_to_yaml(bug.to_vulnerability(),
                                      vulnerability_path)
            # The source of truth is now this yaml file.
            bug.source_of_truth = osv.SourceOfTruth.SOURCE_REPO
            exported.append(bug)

        # Commit Vulnerability changes back to the oss-fuzz source repository.
        repo.index.add_all()
        diff = repo.index.diff_to_tree(repo.head.peel().tree)
        if not diff:
            logging.info('No new entries, skipping committing.')
            return

        logging.info('Commiting and pushing new entries')
        if osv.push_source_changes(repo, 'Import from OSS-Fuzz',
                                   self._git_callbacks(oss_fuzz_source)):
            ndb.put_multi(exported)
Beispiel #5
0
    def import_new_oss_fuzz_entries(self, repo, oss_fuzz_source):
        """Import new entries."""
        # TODO(ochang): Make this more efficient by recording whether or not we
        # imported already in Datastore.
        vulnerabilities_path = os.path.join(
            osv.repo_path(repo), oss_fuzz_source.directory_path or '')
        for bug in osv.Bug.query(osv.Bug.status == osv.BugStatus.PROCESSED):
            if not bug.public:
                continue

            source_name, source_id = osv.parse_source_id(bug.source_id)
            if source_name != oss_fuzz_source.name:
                continue

            project_dir = os.path.join(vulnerabilities_path, bug.project)
            os.makedirs(project_dir, exist_ok=True)
            vulnerability_path = os.path.join(
                project_dir, source_id + VULNERABILITY_EXTENSION)

            if os.path.exists(vulnerability_path):
                continue

            logging.info('Writing %s', bug.key.id())
            osv.vulnerability_to_yaml(bug.to_vulnerability_new(),
                                      vulnerability_path)

        # Commit Vulnerability changes back to the oss-fuzz source repository.
        repo.index.add_all()
        diff = repo.index.diff_to_tree(repo.head.peel().tree)
        if not diff:
            logging.info('No new entries, skipping committing.')
            return

        logging.info('Commiting and pushing new entries')
        osv.push_source_changes(repo, 'Import from OSS-Fuzz',
                                self._git_callbacks(oss_fuzz_source))