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 }