/ github / RepositoryAdvisoryVulnerability.py
RepositoryAdvisoryVulnerability.py
  1  ############################ Copyrights and license ############################
  2  #                                                                              #
  3  # Copyright 2023 Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>             #
  4  #                                                                              #
  5  # This file is part of PyGithub.                                               #
  6  # http://pygithub.readthedocs.io/                                              #
  7  #                                                                              #
  8  # PyGithub is free software: you can redistribute it and/or modify it under    #
  9  # the terms of the GNU Lesser General Public License as published by the Free  #
 10  # Software Foundation, either version 3 of the License, or (at your option)    #
 11  # any later version.                                                           #
 12  #                                                                              #
 13  # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY  #
 14  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    #
 15  # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more #
 16  # details.                                                                     #
 17  #                                                                              #
 18  # You should have received a copy of the GNU Lesser General Public License     #
 19  # along with PyGithub. If not, see <http://www.gnu.org/licenses/>.             #
 20  #                                                                              #
 21  ################################################################################
 22  from __future__ import annotations
 23  
 24  from typing import TYPE_CHECKING, Any, Union
 25  
 26  from typing_extensions import TypedDict
 27  
 28  import github.RepositoryAdvisoryVulnerabilityPackage
 29  from github.GithubObject import Attribute, NonCompletableGithubObject, NotSet
 30  
 31  if TYPE_CHECKING:
 32      from github.RepositoryAdvisoryVulnerabilityPackage import RepositoryAdvisoryVulnerabilityPackage
 33  
 34  
 35  class SimpleAdvisoryVulnerabilityPackage(TypedDict):
 36      """
 37      A simple package in an advisory.
 38      """
 39  
 40      ecosystem: str
 41      name: str | None
 42  
 43  
 44  class SimpleAdvisoryVulnerability(TypedDict):
 45      """
 46      A simple vulnerability in a security advisory.
 47      """
 48  
 49      package: SimpleAdvisoryVulnerabilityPackage
 50      patched_versions: str | None
 51      vulnerable_functions: list[str] | None
 52      vulnerable_version_range: str | None
 53  
 54  
 55  AdvisoryVulnerability = Union[SimpleAdvisoryVulnerability, "RepositoryAdvisoryVulnerability"]
 56  
 57  
 58  class RepositoryAdvisoryVulnerability(NonCompletableGithubObject):
 59      """
 60      This class represents a package that is vulnerable to a parent SecurityAdvisory.
 61      The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories
 62      """
 63  
 64      @property
 65      def package(
 66          self,
 67      ) -> RepositoryAdvisoryVulnerabilityPackage:
 68          """
 69          :type: :class:`github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability`
 70          """
 71          return self._package.value
 72  
 73      @property
 74      def patched_versions(self) -> str:
 75          """
 76          :type: string
 77          """
 78          return self._patched_versions.value
 79  
 80      @property
 81      def vulnerable_functions(self) -> list[str] | None:
 82          """
 83          :type: list of string
 84          """
 85          return self._vulnerable_functions.value
 86  
 87      @property
 88      def vulnerable_version_range(self) -> str | None:
 89          """
 90          :type: string
 91          """
 92          return self._vulnerable_version_range.value
 93  
 94      def _initAttributes(self) -> None:
 95          self._package: Attribute[RepositoryAdvisoryVulnerabilityPackage] = NotSet
 96          self._patched_versions: Attribute[str] = NotSet
 97          self._vulnerable_functions: Attribute[list[str]] = NotSet
 98          self._vulnerable_version_range: Attribute[str] = NotSet
 99  
100      def _useAttributes(self, attributes: dict[str, Any]) -> None:
101          if "package" in attributes:  # pragma no branch
102              self._package = self._makeClassAttribute(
103                  github.RepositoryAdvisoryVulnerabilityPackage.RepositoryAdvisoryVulnerabilityPackage,
104                  attributes["package"],
105              )
106          if "patched_versions" in attributes:  # pragma no branch
107              self._patched_versions = self._makeStringAttribute(attributes["patched_versions"])
108          if "vulnerable_functions" in attributes:  # pragma no branch
109              self._vulnerable_functions = self._makeListOfStringsAttribute(attributes["vulnerable_functions"])
110          if "vulnerable_version_range" in attributes:  # pragma no branch
111              self._vulnerable_version_range = self._makeStringAttribute(attributes["vulnerable_version_range"])
112  
113      @classmethod
114      def _validate_vulnerability(cls, vulnerability: AdvisoryVulnerability) -> None:
115          assert isinstance(vulnerability, (dict, cls)), vulnerability
116          if isinstance(vulnerability, dict):
117              assert "package" in vulnerability, vulnerability
118              package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"]
119              assert isinstance(package, dict), package
120              assert "ecosystem" in package, package
121              assert isinstance(package["ecosystem"], str), package
122              assert "name" in package, package
123              assert isinstance(package["name"], (str, type(None))), package
124              assert "patched_versions" in vulnerability, vulnerability
125              assert isinstance(vulnerability["patched_versions"], (str, type(None))), vulnerability
126              assert "vulnerable_functions" in vulnerability, vulnerability
127              assert isinstance(vulnerability["vulnerable_functions"], (list, type(None))), vulnerability
128              assert "vulnerable_functions" in vulnerability, vulnerability
129              assert (
130                  all(isinstance(vf, str) for vf in vulnerability["vulnerable_functions"])
131                  if vulnerability["vulnerable_functions"] is not None
132                  else True
133              ), vulnerability
134              assert "vulnerable_version_range" in vulnerability, vulnerability
135              assert isinstance(vulnerability["vulnerable_version_range"], (str, type(None))), vulnerability
136  
137          else:
138              assert (
139                  vulnerability.package
140                  is github.RepositoryAdvisoryVulnerabilityPackage.RepositoryAdvisoryVulnerabilityPackage
141              ), vulnerability
142  
143      @staticmethod
144      def _to_github_dict(
145          vulnerability: AdvisoryVulnerability,
146      ) -> SimpleAdvisoryVulnerability:
147          if isinstance(vulnerability, dict):
148              vulnerability_package: SimpleAdvisoryVulnerabilityPackage = vulnerability["package"]
149              return {
150                  "package": {
151                      "ecosystem": vulnerability_package["ecosystem"],
152                      "name": vulnerability_package["name"],
153                  },
154                  "patched_versions": vulnerability["patched_versions"],
155                  "vulnerable_functions": vulnerability["vulnerable_functions"],
156                  "vulnerable_version_range": vulnerability["vulnerable_version_range"],
157              }
158          return {
159              "package": {
160                  "ecosystem": vulnerability.package.ecosystem,
161                  "name": vulnerability.package.name,
162              },
163              "patched_versions": vulnerability.patched_versions,
164              "vulnerable_functions": vulnerability.vulnerable_functions,
165              "vulnerable_version_range": vulnerability.vulnerable_version_range,
166          }