Files
PyGithub/github/RepositoryAdvisoryVulnerability.py
T

165 lines
7.4 KiB
Python

############################ Copyrights and license ############################
# #
# Copyright 2023 Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> #
# #
# 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 <http://www.gnu.org/licenses/>. #
# #
################################################################################
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,
}