############################ Copyrights and license ############################ # # # Copyright 2023 Jonathan Leitschuh # # # # This file is part of PyGithub. # # http://pygithub.readthedocs.io/ # # # # PyGithub is free software: you can redistribute it and/or modify it under # # the terms of the GNU Lesser General Public License as published by the Free # # Software Foundation, either version 3 of the License, or (at your option) # # any later version. # # # # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # # details. # # # # You should have received a copy of the GNU Lesser General Public License # # along with PyGithub. If not, see . # # # ################################################################################ from typing import List, Optional, Union from typing_extensions import NotRequired, TypedDict import github.GithubObject import github.RepositoryAdvisoryVulnerabilityPackage class SimpleAdvisoryVulnerabilityPackage(TypedDict): """ A simple package in an advisory. """ ecosystem: str name: NotRequired[Optional[str]] class SimpleAdvisoryVulnerability(TypedDict): """ A simple vulnerability in a security advisory. """ package: SimpleAdvisoryVulnerabilityPackage patched_versions: NotRequired[Optional[str]] vulnerable_functions: NotRequired[Optional[List[str]]] vulnerable_version_range: NotRequired[Optional[str]] AdvisoryVulnerability = Union[SimpleAdvisoryVulnerability, "RepositoryAdvisoryVulnerability"] class RepositoryAdvisoryVulnerability(github.GithubObject.NonCompletableGithubObject): """ This class represents a package that is vulnerable to a parent SecurityAdvisory. The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories """ @property def package( self, ) -> github.RepositoryAdvisoryVulnerabilityPackage.RepositoryAdvisoryVulnerabilityPackage: """ :type: :class:`github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability` """ return self._package.value @property def patched_versions(self) -> str: """ :type: string """ return self._patched_versions.value @property def vulnerable_functions(self) -> Optional[List[str]]: """ :type: list of string """ return self._vulnerable_functions.value @property def vulnerable_version_range(self) -> Optional[str]: """ :type: string """ return self._vulnerable_version_range.value # noinspection PyPep8Naming def _initAttributes(self): self._package = github.GithubObject.NotSet self._patched_versions = github.GithubObject.NotSet self._vulnerable_functions = github.GithubObject.NotSet self._vulnerable_version_range = github.GithubObject.NotSet # noinspection PyPep8Naming def _useAttributes(self, attributes): if "package" in attributes: # pragma no branch self._package = self._makeClassAttribute( github.RepositoryAdvisoryVulnerabilityPackage.RepositoryAdvisoryVulnerabilityPackage, attributes["package"], ) if "patched_versions" in attributes: # pragma no branch self._patched_versions = self._makeStringAttribute(attributes["patched_versions"]) if "vulnerable_functions" in attributes: # pragma no branch self._vulnerable_functions = self._makeListOfStringsAttribute(attributes["vulnerable_functions"]) if "vulnerable_version_range" in attributes: # pragma no branch self._vulnerable_version_range = self._makeStringAttribute(attributes["vulnerable_version_range"]) @classmethod def _validate_vulnerability(cls, vulnerability: AdvisoryVulnerability) -> None: assert isinstance(vulnerability, (dict, cls)), vulnerability if isinstance(vulnerability, dict): assert "package" in vulnerability, vulnerability package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"] assert isinstance(package, dict), package assert "ecosystem" in package, package assert isinstance(package["ecosystem"], str), package assert "name" in package, package assert isinstance(package["name"], (str, type(None))), package assert "patched_versions" in vulnerability, vulnerability assert isinstance(vulnerability["patched_versions"], (str, type(None))), vulnerability assert "vulnerable_functions" in vulnerability, vulnerability assert isinstance(vulnerability["vulnerable_functions"], (list, type(None))), vulnerability assert "vulnerable_functions" in vulnerability, vulnerability assert ( all(isinstance(vf, str) for vf in vulnerability["vulnerable_functions"]) if vulnerability["vulnerable_functions"] is not None else True ), vulnerability assert "vulnerable_version_range" in vulnerability, vulnerability assert isinstance(vulnerability["vulnerable_version_range"], (str, type(None))), vulnerability else: assert ( vulnerability.package is github.RepositoryAdvisoryVulnerabilityPackage.RepositoryAdvisoryVulnerabilityPackage ), vulnerability @staticmethod def _to_github_dict( vulnerability: AdvisoryVulnerability, ) -> SimpleAdvisoryVulnerability: if isinstance(vulnerability, dict): vulnerability_package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"] return { "package": { "ecosystem": vulnerability_package["ecosystem"], "name": vulnerability_package["name"], }, "patched_versions": vulnerability["patched_versions"], "vulnerable_functions": vulnerability["vulnerable_functions"], "vulnerable_version_range": vulnerability["vulnerable_version_range"], } return { "package": { "ecosystem": vulnerability.package.ecosystem, "name": vulnerability.package.name, }, "patched_versions": vulnerability.patched_versions, "vulnerable_functions": vulnerability.vulnerable_functions, "vulnerable_version_range": vulnerability.vulnerable_version_range, }