mirror of
https://github.com/status-im/PyGithub.git
synced 2026-08-31 10:51:14 +00:00
Add support for new RepositoryAdvisories API 🎉 (#2483)
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import github.GithubObject
|
||||
|
||||
|
||||
class CWE(github.GithubObject.CompletableGithubObject):
|
||||
"""
|
||||
This class represents a CWE.
|
||||
The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories
|
||||
"""
|
||||
|
||||
@property
|
||||
def cwe_id(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._cwe_id.value
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._name.value
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _initAttributes(self):
|
||||
self._cwe_id = github.GithubObject.NotSet
|
||||
self._name = github.GithubObject.NotSet
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _useAttributes(self, attributes):
|
||||
if "cwe_id" in attributes: # pragma no branch
|
||||
self._cwe_id = self._makeStringAttribute(attributes["cwe_id"])
|
||||
if "name" in attributes: # pragma no branch
|
||||
self._name = self._makeStringAttribute(attributes["name"])
|
||||
@@ -10,7 +10,15 @@
|
||||
# Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
|
||||
# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
|
||||
# Copyright 2016 Sam Corbett <sam.corbett@cloudsoftcorp.com> #
|
||||
# Copyright 2018 Shubham Singh <41840111+singh811@users.noreply.github.com> #
|
||||
# Copyright 2018 h.shi <10385628+AnYeMoWang@users.noreply.github.com> #
|
||||
# Copyright 2018 sfdye <tsfdye@gmail.com> #
|
||||
# Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
|
||||
# Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2023 Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> #
|
||||
# #
|
||||
# This file is part of PyGithub. #
|
||||
# http://pygithub.readthedocs.io/ #
|
||||
@@ -31,6 +39,7 @@
|
||||
################################################################################
|
||||
|
||||
import datetime
|
||||
import typing
|
||||
from operator import itemgetter
|
||||
|
||||
from . import Consts, GithubException
|
||||
@@ -45,6 +54,10 @@ class _NotSetType:
|
||||
|
||||
NotSet = _NotSetType()
|
||||
|
||||
T = typing.TypeVar("T")
|
||||
|
||||
OptionallySet = typing.Union[T, _NotSetType]
|
||||
|
||||
|
||||
class _ValuedAttribute:
|
||||
def __init__(self, value):
|
||||
|
||||
+10
-3
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Callable, Dict, List, Optional, Type, Union
|
||||
from typing import Any, Callable, Dict, List, Optional, Type, Union, TypeVar
|
||||
|
||||
from github.Commit import Commit
|
||||
from github.GistFile import GistFile
|
||||
@@ -96,6 +96,7 @@ class NonCompletableGithubObject(GithubObject):
|
||||
def _completeIfNeeded(self) -> None: ...
|
||||
|
||||
class CompletableGithubObject(GithubObject):
|
||||
_requester: Requester
|
||||
def __eq__(self, other: Any) -> bool: ...
|
||||
def __init__(
|
||||
self,
|
||||
@@ -120,8 +121,14 @@ class _BadAttribute:
|
||||
|
||||
class _NotSetType:
|
||||
def __repr__(self) -> str: ...
|
||||
@property
|
||||
def value(self) -> Any: ...
|
||||
|
||||
NotSet: _NotSetType
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
OptionallySet = Union[T, _NotSetType]
|
||||
|
||||
class _ValuedAttribute:
|
||||
def __init__(self, value: Any) -> None: ...
|
||||
|
||||
NotSet: _NotSetType
|
||||
|
||||
+233
-9
@@ -27,7 +27,7 @@
|
||||
# Copyright 2016 Dustin Spicuzza <dustin@virtualroadside.com> #
|
||||
# Copyright 2016 Enix Yu <enix223@163.com> #
|
||||
# Copyright 2016 Jannis Gebauer <ja.geb@me.com> #
|
||||
# Copyright 2016 Per Øyvind Karlsen <proyvind@moondrake.org> #
|
||||
# Copyright 2016 Per Øyvind Karlsen <proyvind@moondrake.org> #
|
||||
# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
|
||||
# Copyright 2016 Sylvus <Sylvus@users.noreply.github.com> #
|
||||
# Copyright 2016 fukatani <nannyakannya@gmail.com> #
|
||||
@@ -39,34 +39,69 @@
|
||||
# Copyright 2017 Jannis Gebauer <ja.geb@me.com> #
|
||||
# Copyright 2017 Jason White <jasonwhite@users.noreply.github.com> #
|
||||
# Copyright 2017 Jimmy Zelinskie <jimmy.zelinskie+git@gmail.com> #
|
||||
# Copyright 2017 Nhomar Hernández [Vauxoo] <nhomar@vauxoo.com> #
|
||||
# Copyright 2017 Nhomar Hernández [Vauxoo] <nhomar@vauxoo.com> #
|
||||
# Copyright 2017 Simon <spam@esemi.ru> #
|
||||
# Copyright 2018 Aaron L. Levine <allevin@sandia.gov> #
|
||||
# Copyright 2018 AetherDeity <aetherdeity+github@gmail.com> #
|
||||
# Copyright 2018 Alice GIRARD <bouhahah@gmail.com> #
|
||||
# Copyright 2018 Andrew Smith <espadav8@gmail.com> #
|
||||
# Copyright 2018 Benoit Latinier <benoit@latinier.fr> #
|
||||
# Copyright 2018 Brian Torres-Gil <btorres-gil@paloaltonetworks.com> #
|
||||
# Copyright 2018 Hayden Fuss <wifu1234@gmail.com> #
|
||||
# Copyright 2018 Ilya Konstantinov <ilya.konstantinov@gmail.com> #
|
||||
# Copyright 2018 Jacopo Notarstefano <jacopo.notarstefano@gmail.com> #
|
||||
# Copyright 2018 John Hui <j-hui@users.noreply.github.com> #
|
||||
# Copyright 2018 Justin Kufro <jkufro@andrew.cmu.edu> #
|
||||
# Copyright 2018 Mateusz Loskot <mateusz@loskot.net> #
|
||||
# Copyright 2018 Michael Behrisch <oss@behrisch.de> #
|
||||
# Copyright 2018 Nicholas Buse <NicholasBuse@users.noreply.github.com> #
|
||||
# Copyright 2018 Philip May <eniak.info@gmail.com> #
|
||||
# Copyright 2018 Raihaan <31362124+res0nance@users.noreply.github.com> #
|
||||
# Copyright 2018 Shinichi TAMURA <shnch.tmr@gmail.com> #
|
||||
# Copyright 2018 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2018 Vinay Hegde <hegde.vi@husky.neu.edu> #
|
||||
# Copyright 2018 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2018 Will Yardley <wyardley@users.noreply.github.com> #
|
||||
# Copyright 2018 Yossarian King <yggy@blackbirdinteractive.com> #
|
||||
# Copyright 2018 per1234 <accounts@perglass.com> #
|
||||
# Copyright 2018 sechastain <sechastain@gmail.com> #
|
||||
# Copyright 2018 sfdye <tsfdye@gmail.com> #
|
||||
# Copyright 2018 Vinay Hegde <vinayhegde2010@gmail.com> #
|
||||
# Copyright 2018 Justin Kufro <jkufro@andrew.cmu.edu> #
|
||||
# Copyright 2018 Ivan Minno <iminno@andrew.cmu.edu> #
|
||||
# Copyright 2018 Zilei Gu <zileig@andrew.cmu.edu> #
|
||||
# Copyright 2018 Yves Zumbach <yzumbach@andrew.cmu.edu> #
|
||||
# Copyright 2018 Leying Chen <leyingc@andrew.cmu.edu> #
|
||||
# Copyright 2019 Adam Baratz <adam.baratz@gmail.com> #
|
||||
# Copyright 2019 Alex <alexmusa@users.noreply.github.com> #
|
||||
# Copyright 2019 Kevin LaFlamme <k@lamfl.am> #
|
||||
# Copyright 2019 Olof-Joachim Frahm (欧雅福) <olof@macrolet.net> #
|
||||
# Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2019 Tim Gates <tim.gates@iress.com> #
|
||||
# Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2019 Will Li <cuichen.li94@gmail.com> #
|
||||
# Copyright 2020 Alice GIRARD <bouhahah@gmail.com> #
|
||||
# Copyright 2020 Anuj Bansal <bansalanuj1996@gmail.com> #
|
||||
# Copyright 2020 Chris de Graaf <chrisadegraaf@gmail.com> #
|
||||
# Copyright 2020 Dhruv Manilawala <dhruvmanila@gmail.com> #
|
||||
# Copyright 2020 Dominic Davis-Foster <dominic@davis-foster.co.uk> #
|
||||
# Copyright 2020 Florent Clarret <florent.clarret@gmail.com> #
|
||||
# Copyright 2020 Glenn McDonald <testworksau@users.noreply.github.com> #
|
||||
# Copyright 2020 Huw Jones <huwcbjones@outlook.com> #
|
||||
# Copyright 2020 Mark Bromell <markbromell.business@gmail.com> #
|
||||
# Copyright 2020 Max Wittig <max.wittig@siemens.com> #
|
||||
# Copyright 2020 Pascal Hofmann <mail@pascalhofmann.de> #
|
||||
# Copyright 2022 Aleksei Fedotov <aleksei@fedotov.email> #
|
||||
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2020 Tim Gates <tim.gates@iress.com> #
|
||||
# Copyright 2020 Victor Zeng <zacker150@users.noreply.github.com> #
|
||||
# Copyright 2020 ton-katsu <sakamoto.yoshihisa@gmail.com> #
|
||||
# Copyright 2021 Chris Keating <christopherkeating@gmail.com> #
|
||||
# Copyright 2021 Floyd Hightower <floyd.hightower27@gmail.com> #
|
||||
# Copyright 2021 Mark Walker <mark.walker@realbuzz.com> #
|
||||
# Copyright 2021 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2021 Tanner <51724788+lightningboltemoji@users.noreply.github.com> #
|
||||
# Copyright 2021 xmo-odoo <xmo@odoo.com> #
|
||||
# Copyright 2022 Aleksei Fedotov <lexa@cfotr.com> #
|
||||
# Copyright 2022 Eric Nieuwland <eric.nieuwland@gmail.com> #
|
||||
# Copyright 2022 Ibrahim Hussaini <ibrahimhussainialias@outlook.com> #
|
||||
# Copyright 2022 KimSia Sim <245021+simkimsia@users.noreply.github.com> #
|
||||
# Copyright 2022 Marco Köpcke <hello@parakoopa.de> #
|
||||
# Copyright 2023 Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> #
|
||||
# Copyright 2023 Sol Redfern <59831933+Tsuesun@users.noreply.github.com> #
|
||||
# Copyright 2023 Mikhail f. Shiryaev <mr.felixoid@gmail.com> #
|
||||
# #
|
||||
# This file is part of PyGithub. #
|
||||
@@ -89,6 +124,7 @@
|
||||
|
||||
import collections
|
||||
import datetime
|
||||
import typing
|
||||
import urllib.parse
|
||||
from base64 import b64encode
|
||||
|
||||
@@ -132,6 +168,9 @@ import github.PublicKey
|
||||
import github.PullRequest
|
||||
import github.Referrer
|
||||
import github.Repository
|
||||
import github.RepositoryAdvisory
|
||||
import github.RepositoryAdvisoryCredit
|
||||
import github.RepositoryAdvisoryVulnerability
|
||||
import github.RepositoryKey
|
||||
import github.RepositoryPreferences
|
||||
import github.SelfHostedActionsRunner
|
||||
@@ -1472,6 +1511,162 @@ class Repository(github.GithubObject.CompletableGithubObject):
|
||||
self._requester, headers, data, completed=True
|
||||
)
|
||||
|
||||
def create_repository_advisory(
|
||||
self,
|
||||
summary: str,
|
||||
description: str,
|
||||
severity_or_cvss_vector_string: str,
|
||||
cve_id: typing.Optional[str] = None,
|
||||
vulnerabilities: typing.Optional[
|
||||
typing.Iterable[
|
||||
github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability
|
||||
]
|
||||
] = None,
|
||||
cwe_ids: typing.Optional[typing.Iterable[str]] = None,
|
||||
credits: typing.Optional[
|
||||
typing.Iterable[github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit]
|
||||
] = None,
|
||||
) -> github.RepositoryAdvisory.RepositoryAdvisory:
|
||||
"""
|
||||
:calls: `POST /repos/{owner}/{repo}/security-advisories <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
:param summary: string
|
||||
:param description: string
|
||||
:param severity_or_cvss_vector_string: string
|
||||
:param cve_id: string
|
||||
:param vulnerabilities: iterable of :class:`github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability`
|
||||
:param cwe_ids: iterable of string
|
||||
:param credits: iterable of :class:`github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit`
|
||||
:rtype: :class:`github.RepositoryAdvisory.RepositoryAdvisory`
|
||||
"""
|
||||
return self.__create_repository_advisory(
|
||||
summary=summary,
|
||||
description=description,
|
||||
severity_or_cvss_vector_string=severity_or_cvss_vector_string,
|
||||
cve_id=cve_id,
|
||||
vulnerabilities=vulnerabilities,
|
||||
cwe_ids=cwe_ids,
|
||||
credits=credits,
|
||||
private_vulnerability_reporting=False,
|
||||
)
|
||||
|
||||
def report_security_vulnerability(
|
||||
self,
|
||||
summary: str,
|
||||
description: str,
|
||||
severity_or_cvss_vector_string: str,
|
||||
cve_id: typing.Optional[str] = None,
|
||||
vulnerabilities: typing.Optional[
|
||||
typing.Iterable[
|
||||
github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability
|
||||
]
|
||||
] = None,
|
||||
cwe_ids: typing.Optional[typing.Iterable[str]] = None,
|
||||
credits: typing.Optional[
|
||||
typing.Iterable[github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit]
|
||||
] = None,
|
||||
) -> github.RepositoryAdvisory.RepositoryAdvisory:
|
||||
"""
|
||||
:calls: `POST /repos/{owner}/{repo}/security-advisories/reports <https://docs.github.com/en/rest/security-advisories/repository-advisories#privately-report-a-security-vulnerability>`_
|
||||
:param summary: string
|
||||
:param description: string
|
||||
:param severity_or_cvss_vector_string: string
|
||||
:param cve_id: string
|
||||
:param vulnerabilities: iterable of :class:`github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability`
|
||||
:param cwe_ids: iterable of string
|
||||
:param credits: iterable of :class:`github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit`
|
||||
:rtype: :class:`github.RepositoryAdvisory.RepositoryAdvisory`
|
||||
"""
|
||||
return self.__create_repository_advisory(
|
||||
summary=summary,
|
||||
description=description,
|
||||
severity_or_cvss_vector_string=severity_or_cvss_vector_string,
|
||||
cve_id=cve_id,
|
||||
vulnerabilities=vulnerabilities,
|
||||
cwe_ids=cwe_ids,
|
||||
credits=credits,
|
||||
private_vulnerability_reporting=True,
|
||||
)
|
||||
|
||||
def __create_repository_advisory(
|
||||
self,
|
||||
summary: str,
|
||||
description: str,
|
||||
severity_or_cvss_vector_string: str,
|
||||
cve_id: typing.Optional[str],
|
||||
vulnerabilities: typing.Optional[
|
||||
typing.Iterable[
|
||||
github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability
|
||||
]
|
||||
],
|
||||
cwe_ids: typing.Optional[typing.Iterable[str]],
|
||||
credits: typing.Optional[
|
||||
typing.Iterable[github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit]
|
||||
],
|
||||
private_vulnerability_reporting: bool,
|
||||
) -> github.RepositoryAdvisory.RepositoryAdvisory:
|
||||
if vulnerabilities is None:
|
||||
vulnerabilities = []
|
||||
if cwe_ids is None:
|
||||
cwe_ids = []
|
||||
assert isinstance(summary, str), summary
|
||||
assert isinstance(description, str), description
|
||||
assert isinstance(
|
||||
severity_or_cvss_vector_string, str
|
||||
), severity_or_cvss_vector_string
|
||||
assert isinstance(cve_id, (str, type(None))), cve_id
|
||||
assert isinstance(vulnerabilities, typing.Iterable), vulnerabilities
|
||||
for vulnerability in vulnerabilities:
|
||||
# noinspection PyProtectedMember
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._validate_vulnerability(
|
||||
vulnerability
|
||||
)
|
||||
assert isinstance(cwe_ids, typing.Iterable), cwe_ids
|
||||
assert all(isinstance(element, str) for element in cwe_ids), cwe_ids
|
||||
assert isinstance(credits, (typing.Iterable, type(None))), credits
|
||||
if credits is not None:
|
||||
for credit in credits:
|
||||
# noinspection PyProtectedMember
|
||||
github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit._validate_credit(
|
||||
credit
|
||||
)
|
||||
# noinspection PyProtectedMember
|
||||
post_parameters = {
|
||||
"summary": summary,
|
||||
"description": description,
|
||||
"vulnerabilities": [
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._to_github_dict(
|
||||
vulnerability
|
||||
)
|
||||
for vulnerability in vulnerabilities
|
||||
],
|
||||
"cwe_ids": list(cwe_ids),
|
||||
}
|
||||
if cve_id is not None:
|
||||
post_parameters["cve_id"] = cve_id
|
||||
if credits is not None:
|
||||
# noinspection PyProtectedMember
|
||||
post_parameters["credits"] = [
|
||||
github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit._to_github_dict(
|
||||
credit
|
||||
)
|
||||
for credit in credits
|
||||
]
|
||||
if severity_or_cvss_vector_string.startswith("CVSS:"):
|
||||
post_parameters["cvss_vector_string"] = severity_or_cvss_vector_string
|
||||
else:
|
||||
post_parameters["severity"] = severity_or_cvss_vector_string
|
||||
if private_vulnerability_reporting:
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"POST", f"{self.url}/security-advisories/reports", input=post_parameters
|
||||
)
|
||||
else:
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"POST", f"{self.url}/security-advisories", input=post_parameters
|
||||
)
|
||||
return github.RepositoryAdvisory.RepositoryAdvisory(
|
||||
self._requester, headers, data, completed=True
|
||||
)
|
||||
|
||||
def create_repository_dispatch(
|
||||
self, event_type, client_payload=github.GithubObject.NotSet
|
||||
):
|
||||
@@ -2228,6 +2423,35 @@ class Repository(github.GithubObject.CompletableGithubObject):
|
||||
),
|
||||
}
|
||||
|
||||
def get_repository_advisories(
|
||||
self,
|
||||
) -> "github.PaginatedList.PaginatedList[github.RepositoryAdvisory.RepositoryAdvisory]":
|
||||
"""
|
||||
:calls: `GET /repos/{owner}/{repo}/security-advisories <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
:rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.RepositoryAdvisory.RepositoryAdvisory`
|
||||
"""
|
||||
return github.PaginatedList.PaginatedList(
|
||||
github.RepositoryAdvisory.RepositoryAdvisory,
|
||||
self._requester,
|
||||
f"{self.url}/security-advisories",
|
||||
None,
|
||||
)
|
||||
|
||||
def get_repository_advisory(
|
||||
self, ghsa: str
|
||||
) -> github.RepositoryAdvisory.RepositoryAdvisory:
|
||||
"""
|
||||
:calls: `GET /repos/{owner}/{repo}/security-advisories/{ghsa} <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
:param ghsa: string
|
||||
:rtype: :class:`github.RepositoryAdvisory.RepositoryAdvisory`
|
||||
"""
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"GET", f"{self.url}/security-advisories/{ghsa}"
|
||||
)
|
||||
return github.RepositoryAdvisory.RepositoryAdvisory(
|
||||
self._requester, headers, data, completed=True
|
||||
)
|
||||
|
||||
def update_file(
|
||||
self,
|
||||
path,
|
||||
|
||||
+29
-1
@@ -1,5 +1,5 @@
|
||||
from datetime import date, datetime
|
||||
from typing import Any, Dict, List, Optional, Union, overload
|
||||
from typing import Any, Dict, List, Optional, Union, overload, Iterable
|
||||
|
||||
from github.Artifact import Artifact
|
||||
from github.AuthenticatedUser import AuthenticatedUser
|
||||
@@ -43,6 +43,12 @@ from github.PublicKey import PublicKey
|
||||
from github.PullRequest import PullRequest
|
||||
from github.PullRequestComment import PullRequestComment
|
||||
from github.Referrer import Referrer
|
||||
from github.RepositoryAdvisory import RepositoryAdvisory
|
||||
from github.RepositoryAdvisoryCredit import RepositoryAdvisoryCredit
|
||||
from github.RepositoryAdvisoryVulnerability import (
|
||||
RepositoryAdvisoryVulnerability,
|
||||
AdvisoryVulnerability,
|
||||
)
|
||||
from github.RepositoryKey import RepositoryKey
|
||||
from github.RepositoryPreferences import RepositoryPreferences
|
||||
from github.SelfHostedActionsRunner import SelfHostedActionsRunner
|
||||
@@ -134,6 +140,8 @@ class Repository(CompletableGithubObject):
|
||||
transient_environment: Union[bool, _NotSetType] = ...,
|
||||
production_environment: Union[bool, _NotSetType] = ...,
|
||||
) -> Deployment: ...
|
||||
def get_repository_advisories(self) -> PaginatedList[RepositoryAdvisory]: ...
|
||||
def get_repository_advisory(self, ghsa: str) -> RepositoryAdvisory: ...
|
||||
def create_file(
|
||||
self,
|
||||
path: str,
|
||||
@@ -242,6 +250,26 @@ class Repository(CompletableGithubObject):
|
||||
maintainer_can_modify: _NotSetType,
|
||||
issue: Issue,
|
||||
) -> PullRequest: ...
|
||||
def create_repository_advisory(
|
||||
self,
|
||||
summary: str,
|
||||
description: str,
|
||||
severity_or_cvss_vector_string: str,
|
||||
cve_id: Optional[str] = ...,
|
||||
vulnerabilities: Optional[Iterable[AdvisoryVulnerability]] = ...,
|
||||
cwe_ids: Optional[Iterable[str]] = ...,
|
||||
credits: Optional[Iterable[RepositoryAdvisoryCredit]] = ...,
|
||||
) -> RepositoryAdvisory: ...
|
||||
def report_security_vulnerability(
|
||||
self,
|
||||
summary: str,
|
||||
description: str,
|
||||
severity_or_cvss_vector_string: str,
|
||||
cve_id: Optional[str] = ...,
|
||||
vulnerabilities: Optional[Iterable[AdvisoryVulnerability]] = ...,
|
||||
cwe_ids: Optional[Iterable[str]] = ...,
|
||||
credits: Optional[Iterable[RepositoryAdvisoryCredit]] = ...,
|
||||
) -> RepositoryAdvisory: ...
|
||||
def create_repository_dispatch(
|
||||
self, event_type: str, client_payload: Union[Dict[str, Any], _NotSetType] = ...
|
||||
) -> bool: ...
|
||||
|
||||
@@ -0,0 +1,558 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import datetime
|
||||
import typing
|
||||
|
||||
import github.GithubObject
|
||||
import github.NamedUser
|
||||
from github.CWE import CWE
|
||||
from github.RepositoryAdvisoryCredit import Credit, RepositoryAdvisoryCredit
|
||||
from github.RepositoryAdvisoryCreditDetailed import RepositoryAdvisoryCreditDetailed
|
||||
from github.RepositoryAdvisoryVulnerability import (
|
||||
AdvisoryVulnerability,
|
||||
RepositoryAdvisoryVulnerability,
|
||||
)
|
||||
from github.Requester import Requester
|
||||
|
||||
|
||||
class RepositoryAdvisory(github.GithubObject.NonCompletableGithubObject):
|
||||
"""
|
||||
This class represents a RepositoryAdvisory.
|
||||
The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories
|
||||
"""
|
||||
|
||||
_requester: Requester
|
||||
|
||||
def __repr__(self):
|
||||
return self.get__repr__({"ghsa_id": self.ghsa_id, "summary": self.summary})
|
||||
|
||||
@property
|
||||
def author(self) -> "github.NamedUser.NamedUser":
|
||||
"""
|
||||
:type: :class:`github.NamedUser.NamedUser`
|
||||
"""
|
||||
return self._author.value
|
||||
|
||||
@property
|
||||
def closed_at(self) -> datetime.datetime:
|
||||
"""
|
||||
:type: datetime.datetime
|
||||
"""
|
||||
return self._closed_at.value
|
||||
|
||||
@property
|
||||
def created_at(self) -> datetime.datetime:
|
||||
"""
|
||||
:type: datetime.datetime
|
||||
"""
|
||||
return self._created_at.value
|
||||
|
||||
@property
|
||||
def credits(
|
||||
self,
|
||||
) -> typing.List[RepositoryAdvisoryCredit]:
|
||||
"""
|
||||
:type: list of :class:`github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit`
|
||||
"""
|
||||
return self._credits.value
|
||||
|
||||
@property
|
||||
def credits_detailed(
|
||||
self,
|
||||
) -> typing.List[RepositoryAdvisoryCreditDetailed]:
|
||||
"""
|
||||
:type: list of :class:`github.RepositoryAdvisoryCreditDetailed.RepositoryAdvisoryCreditDetailed`
|
||||
"""
|
||||
return self._credits_detailed.value
|
||||
|
||||
@property
|
||||
def cve_id(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._cve_id.value
|
||||
|
||||
@property
|
||||
def cwe_ids(self) -> typing.List[str]:
|
||||
"""
|
||||
:type: list of string
|
||||
"""
|
||||
return self._cwe_ids.value
|
||||
|
||||
@property
|
||||
def cwes(self) -> typing.List[CWE]:
|
||||
"""
|
||||
:type: list of :class:`github.CWE.CWE`
|
||||
"""
|
||||
return self._cwes.value
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._description.value
|
||||
|
||||
@property
|
||||
def ghsa_id(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._ghsa_id.value
|
||||
|
||||
@property
|
||||
def html_url(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._html_url.value
|
||||
|
||||
@property
|
||||
def published_at(self) -> datetime.datetime:
|
||||
"""
|
||||
:type: datetime.datetime
|
||||
"""
|
||||
return self._published_at.value
|
||||
|
||||
@property
|
||||
def severity(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._severity.value
|
||||
|
||||
@property
|
||||
def state(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._state.value
|
||||
|
||||
@property
|
||||
def summary(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._summary.value
|
||||
|
||||
@property
|
||||
def updated_at(self) -> datetime.datetime:
|
||||
"""
|
||||
:type: datetime.datetime
|
||||
"""
|
||||
return self._updated_at.value
|
||||
|
||||
@property
|
||||
def url(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._url.value
|
||||
|
||||
@property
|
||||
def vulnerabilities(
|
||||
self,
|
||||
) -> typing.List[RepositoryAdvisoryVulnerability]:
|
||||
"""
|
||||
:type: list of :class:`github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability`
|
||||
"""
|
||||
return self._vulnerabilities.value
|
||||
|
||||
@property
|
||||
def withdrawn_at(self) -> datetime.datetime:
|
||||
"""
|
||||
:type: datetime.datetime
|
||||
"""
|
||||
return self._withdrawn_at.value
|
||||
|
||||
def add_vulnerability(
|
||||
self,
|
||||
ecosystem: str,
|
||||
package_name: typing.Optional[str] = None,
|
||||
vulnerable_version_range: typing.Optional[str] = None,
|
||||
patched_versions: typing.Optional[str] = None,
|
||||
vulnerable_functions: typing.Optional[typing.List[str]] = None,
|
||||
):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`\
|
||||
:param ecosystem: string
|
||||
:param package_name: string
|
||||
:param vulnerable_version_range: string
|
||||
:param patched_versions: string
|
||||
:param vulnerable_functions: list of string
|
||||
"""
|
||||
return self.add_vulnerabilities(
|
||||
[
|
||||
{
|
||||
"package": {
|
||||
"ecosystem": ecosystem,
|
||||
"name": package_name,
|
||||
},
|
||||
"vulnerable_version_range": vulnerable_version_range,
|
||||
"patched_versions": patched_versions,
|
||||
"vulnerable_functions": vulnerable_functions,
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
def add_vulnerabilities(
|
||||
self, vulnerabilities: typing.Iterable[AdvisoryVulnerability]
|
||||
):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
:param vulnerabilities: iterable of :class:`github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability`
|
||||
"""
|
||||
assert isinstance(vulnerabilities, typing.Iterable), vulnerabilities
|
||||
for vulnerability in vulnerabilities:
|
||||
# noinspection PyProtectedMember
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._validate_vulnerability(
|
||||
vulnerability
|
||||
)
|
||||
# noinspection PyProtectedMember
|
||||
post_parameters = {
|
||||
"vulnerabilities": [
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._to_github_dict(
|
||||
vulnerability
|
||||
)
|
||||
for vulnerability in (self.vulnerabilities + list(vulnerabilities))
|
||||
]
|
||||
}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=post_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def offer_credit(
|
||||
self,
|
||||
login_or_user: typing.Union[str, "github.NamedUser.NamedUser"],
|
||||
credit_type: str,
|
||||
):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
Offers credit to a user for a vulnerability in a repository.
|
||||
Unless you are giving credit to yourself, the user having credit offered will need to explicitly accept the credit.
|
||||
:param login_or_user: string username or :class:`github.NamedUser.NamedUser`
|
||||
:param credit_type: string
|
||||
"""
|
||||
self.offer_credits([{"login": login_or_user, "type": credit_type}])
|
||||
|
||||
def offer_credits(
|
||||
self,
|
||||
credited: typing.Iterable["Credit"],
|
||||
):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
Offers credit to a list of users for a vulnerability in a repository.
|
||||
Unless you are giving credit to yourself, the user having credit offered will need to explicitly accept the credit.
|
||||
:param credited: iterable of dict with keys "login" and "type"
|
||||
"""
|
||||
assert isinstance(credited, typing.Iterable), credited
|
||||
for credit in credited:
|
||||
# noinspection PyProtectedMember
|
||||
RepositoryAdvisoryCredit._validate_credit(credit)
|
||||
# noinspection PyProtectedMember
|
||||
patch_parameters = {
|
||||
"credits": [
|
||||
RepositoryAdvisoryCredit._to_github_dict(credit)
|
||||
for credit in (self.credits + list(credited))
|
||||
]
|
||||
}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def revoke_credit(
|
||||
self, login_or_user: typing.Union[str, "github.NamedUser.NamedUser"]
|
||||
):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
:param login_or_user: string username or :class:`github.NamedUser.NamedUser`
|
||||
"""
|
||||
assert isinstance(
|
||||
login_or_user, (str, github.NamedUser.NamedUser)
|
||||
), login_or_user
|
||||
if isinstance(login_or_user, github.NamedUser.NamedUser):
|
||||
login_or_user = login_or_user.login
|
||||
patch_parameters = {
|
||||
"credits": [
|
||||
dict(login=credit.login, type=credit.type)
|
||||
for credit in self.credits
|
||||
if credit.login != login_or_user
|
||||
]
|
||||
}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def clear_credits(self):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
"""
|
||||
patch_parameters = {"credits": []}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def edit(
|
||||
self,
|
||||
summary: github.GithubObject.OptionallySet[str] = github.GithubObject.NotSet,
|
||||
description: github.GithubObject.OptionallySet[
|
||||
str
|
||||
] = github.GithubObject.NotSet,
|
||||
severity_or_cvss_vector_string: github.GithubObject.OptionallySet[
|
||||
str
|
||||
] = github.GithubObject.NotSet,
|
||||
cve_id: github.GithubObject.OptionallySet[str] = github.GithubObject.NotSet,
|
||||
vulnerabilities: github.GithubObject.OptionallySet[
|
||||
typing.Iterable[AdvisoryVulnerability]
|
||||
] = github.GithubObject.NotSet,
|
||||
cwe_ids: github.GithubObject.OptionallySet[
|
||||
typing.Iterable[str]
|
||||
] = github.GithubObject.NotSet,
|
||||
credits: github.GithubObject.OptionallySet[
|
||||
typing.Iterable[Credit]
|
||||
] = github.GithubObject.NotSet,
|
||||
state: github.GithubObject.OptionallySet[str] = github.GithubObject.NotSet,
|
||||
) -> "RepositoryAdvisory":
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`_
|
||||
:param summary: string
|
||||
:param description: string
|
||||
:param severity_or_cvss_vector_string: string
|
||||
:param cve_id: string
|
||||
:param vulnerabilities: iterable of :class:`github.RepositoryAdvisoryVulnerability.AdvisoryVulnerability`
|
||||
:param cwe_ids: iterable of string
|
||||
:param credits: iterable of :class:`github.RepositoryAdvisoryCredit.Credit`
|
||||
:param state: string
|
||||
:rtype: :class:`github.RepositoryAdvisory.RepositoryAdvisory`
|
||||
"""
|
||||
assert summary is github.GithubObject.NotSet or isinstance(
|
||||
summary, str
|
||||
), summary
|
||||
assert description is github.GithubObject.NotSet or isinstance(
|
||||
description, str
|
||||
), description
|
||||
assert (
|
||||
severity_or_cvss_vector_string is github.GithubObject.NotSet
|
||||
or isinstance(severity_or_cvss_vector_string, str)
|
||||
), (severity_or_cvss_vector_string)
|
||||
assert cve_id is github.GithubObject.NotSet or isinstance(cve_id, str), cve_id
|
||||
assert vulnerabilities is github.GithubObject.NotSet or isinstance(
|
||||
vulnerabilities, typing.Iterable
|
||||
), vulnerabilities
|
||||
if isinstance(vulnerabilities, typing.Iterable):
|
||||
for vulnerability in vulnerabilities:
|
||||
# noinspection PyProtectedMember
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._validate_vulnerability(
|
||||
vulnerability
|
||||
)
|
||||
assert cwe_ids is github.GithubObject.NotSet or (
|
||||
isinstance(cwe_ids, typing.Iterable)
|
||||
and all(isinstance(element, str) for element in cwe_ids)
|
||||
), cwe_ids
|
||||
if isinstance(credits, typing.Iterable):
|
||||
for credit in credits:
|
||||
# noinspection PyProtectedMember
|
||||
github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit._validate_credit(
|
||||
credit
|
||||
)
|
||||
assert state is github.GithubObject.NotSet or isinstance(state, str), state
|
||||
patch_parameters: typing.Dict[str, typing.Any] = dict()
|
||||
if summary is not github.GithubObject.NotSet:
|
||||
patch_parameters["summary"] = summary
|
||||
if description is not github.GithubObject.NotSet:
|
||||
patch_parameters["description"] = description
|
||||
if isinstance(severity_or_cvss_vector_string, str):
|
||||
if severity_or_cvss_vector_string.startswith("CVSS:"):
|
||||
patch_parameters["cvss_vector_string"] = severity_or_cvss_vector_string
|
||||
else:
|
||||
patch_parameters["severity"] = severity_or_cvss_vector_string
|
||||
if cve_id is not github.GithubObject.NotSet:
|
||||
patch_parameters["cve_id"] = cve_id
|
||||
if isinstance(vulnerabilities, typing.Iterable):
|
||||
# noinspection PyProtectedMember
|
||||
patch_parameters["vulnerabilities"] = [
|
||||
github.RepositoryAdvisoryVulnerability.RepositoryAdvisoryVulnerability._to_github_dict(
|
||||
vulnerability
|
||||
)
|
||||
for vulnerability in vulnerabilities
|
||||
]
|
||||
if isinstance(cwe_ids, typing.Iterable):
|
||||
patch_parameters["cwe_ids"] = list(cwe_ids)
|
||||
if isinstance(credits, typing.Iterable):
|
||||
# noinspection PyProtectedMember
|
||||
patch_parameters["credits"] = [
|
||||
github.RepositoryAdvisoryCredit.RepositoryAdvisoryCredit._to_github_dict(
|
||||
credit
|
||||
)
|
||||
for credit in credits
|
||||
]
|
||||
if state is not github.GithubObject.NotSet:
|
||||
patch_parameters["state"] = state
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
return self
|
||||
|
||||
def accept_report(self):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
Accepts the advisory reported from an external reporter via private vulnerability reporting.
|
||||
"""
|
||||
patch_parameters = {"state": "draft"}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def publish(self):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
Publishes the advisory.
|
||||
"""
|
||||
patch_parameters = {"state": "published"}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
:calls: `PATCH /repos/{owner}/{repo}/security-advisories/:advisory_id <https://docs.github.com/en/rest/security-advisories/repository-advisories>`
|
||||
Closes the advisory.
|
||||
"""
|
||||
patch_parameters = {"state": "closed"}
|
||||
headers, data = self._requester.requestJsonAndCheck(
|
||||
"PATCH",
|
||||
self.url,
|
||||
input=patch_parameters,
|
||||
)
|
||||
self._useAttributes(data)
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
# noinspection PyPep8Naming
|
||||
def _initAttributes(self):
|
||||
self._author = github.GithubObject.NotSet
|
||||
self._closed_at = github.GithubObject.NotSet
|
||||
self._created_at = github.GithubObject.NotSet
|
||||
self._credits = github.GithubObject.NotSet
|
||||
self._credits_detailed = github.GithubObject.NotSet
|
||||
self._cve_id = github.GithubObject.NotSet
|
||||
self._cwe_ids = github.GithubObject.NotSet
|
||||
self._cwes = github.GithubObject.NotSet
|
||||
self._description = github.GithubObject.NotSet
|
||||
self._ghsa_id = github.GithubObject.NotSet
|
||||
self._html_url = github.GithubObject.NotSet
|
||||
self._published_at = github.GithubObject.NotSet
|
||||
self._severity = github.GithubObject.NotSet
|
||||
self._state = github.GithubObject.NotSet
|
||||
self._summary = github.GithubObject.NotSet
|
||||
self._updated_at = github.GithubObject.NotSet
|
||||
self._url = github.GithubObject.NotSet
|
||||
self._vulnerabilities = github.GithubObject.NotSet
|
||||
self._withdrawn_at = github.GithubObject.NotSet
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _useAttributes(self, attributes):
|
||||
if "author" in attributes: # pragma no branch
|
||||
self._author = self._makeClassAttribute(
|
||||
github.NamedUser.NamedUser, attributes["author"]
|
||||
)
|
||||
if "closed_at" in attributes: # pragma no branch
|
||||
assert attributes["closed_at"] is None or isinstance(
|
||||
attributes["closed_at"], str
|
||||
), attributes["closed_at"]
|
||||
self._closed_at = self._makeDatetimeAttribute(attributes["closed_at"])
|
||||
if "created_at" in attributes: # pragma no branch
|
||||
assert attributes["created_at"] is None or isinstance(
|
||||
attributes["created_at"], str
|
||||
), attributes["created_at"]
|
||||
self._created_at = self._makeDatetimeAttribute(attributes["created_at"])
|
||||
if "credits" in attributes: # pragma no branch
|
||||
self._credits = self._makeListOfClassesAttribute(
|
||||
RepositoryAdvisoryCredit,
|
||||
attributes["credits"],
|
||||
)
|
||||
if "credits_detailed" in attributes: # pragma no branch
|
||||
self._credits_detailed = self._makeListOfClassesAttribute(
|
||||
RepositoryAdvisoryCreditDetailed,
|
||||
attributes["credits_detailed"],
|
||||
)
|
||||
if "cve_id" in attributes: # pragma no branch
|
||||
self._cve_id = self._makeStringAttribute(attributes["cve_id"])
|
||||
if "cwe_ids" in attributes: # pragma no branch
|
||||
self._cwe_ids = self._makeListOfStringsAttribute(attributes["cwe_ids"])
|
||||
if "cwes" in attributes: # pragma no branch
|
||||
self._cwes = self._makeListOfClassesAttribute(CWE, attributes["cwes"])
|
||||
if "description" in attributes: # pragma no branch
|
||||
self._description = self._makeStringAttribute(attributes["description"])
|
||||
if "ghsa_id" in attributes: # pragma no branch
|
||||
self._ghsa_id = self._makeStringAttribute(attributes["ghsa_id"])
|
||||
if "html_url" in attributes: # pragma no branch
|
||||
self._html_url = self._makeStringAttribute(attributes["html_url"])
|
||||
if "published_at" in attributes: # pragma no branch
|
||||
assert attributes["published_at"] is None or isinstance(
|
||||
attributes["published_at"], str
|
||||
), attributes["published_at"]
|
||||
self._published_at = self._makeDatetimeAttribute(attributes["published_at"])
|
||||
if "severity" in attributes: # pragma no branch
|
||||
self._severity = self._makeStringAttribute(attributes["severity"])
|
||||
if "state" in attributes: # pragma no branch
|
||||
self._state = self._makeStringAttribute(attributes["state"])
|
||||
if "summary" in attributes: # pragma no branch
|
||||
self._summary = self._makeStringAttribute(attributes["summary"])
|
||||
if "updated_at" in attributes: # pragma no branch
|
||||
assert attributes["updated_at"] is None or isinstance(
|
||||
attributes["updated_at"], str
|
||||
), attributes["updated_at"]
|
||||
self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"])
|
||||
if "url" in attributes: # pragma no branch
|
||||
self._url = self._makeStringAttribute(attributes["url"])
|
||||
if "vulnerabilities" in attributes: # pragma no branch
|
||||
self._vulnerabilities = self._makeListOfClassesAttribute(
|
||||
RepositoryAdvisoryVulnerability,
|
||||
attributes["vulnerabilities"],
|
||||
)
|
||||
if "withdrawn_at" in attributes: # pragma no branch
|
||||
assert attributes["withdrawn_at"] is None or isinstance(
|
||||
attributes["withdrawn_at"], str
|
||||
), attributes["withdrawn_at"]
|
||||
self._withdrawn_at = self._makeDatetimeAttribute(attributes["withdrawn_at"])
|
||||
@@ -0,0 +1,111 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import typing
|
||||
|
||||
import github.GithubObject
|
||||
import github.NamedUser
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
# TypedDict is only available in Python 3.8 and later
|
||||
class SimpleCredit(typing.TypedDict):
|
||||
"""
|
||||
A simple credit for a security advisory.
|
||||
"""
|
||||
|
||||
login: typing.Union[str, "github.NamedUser.NamedUser"]
|
||||
type: str
|
||||
|
||||
else:
|
||||
SimpleCredit = typing.Dict[str, typing.Any]
|
||||
|
||||
Credit = typing.Union[SimpleCredit, "RepositoryAdvisoryCredit"]
|
||||
|
||||
|
||||
class RepositoryAdvisoryCredit(github.GithubObject.NonCompletableGithubObject):
|
||||
"""
|
||||
This class represents a credit that is assigned to a SecurityAdvisory.
|
||||
The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories
|
||||
"""
|
||||
|
||||
@property
|
||||
def login(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._login.value
|
||||
|
||||
@property
|
||||
def type(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._type.value
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _initAttributes(self):
|
||||
self._login = github.GithubObject.NotSet
|
||||
self._type = github.GithubObject.NotSet
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _useAttributes(self, attributes):
|
||||
if "login" in attributes: # pragma no branch
|
||||
self._login = self._makeStringAttribute(attributes["login"])
|
||||
if "type" in attributes: # pragma no branch
|
||||
self._type = self._makeStringAttribute(attributes["type"])
|
||||
|
||||
@staticmethod
|
||||
def _validate_credit(credit: Credit) -> None:
|
||||
assert isinstance(credit, (dict, RepositoryAdvisoryCredit)), credit
|
||||
if isinstance(credit, dict):
|
||||
assert "login" in credit, credit
|
||||
assert "type" in credit, credit
|
||||
assert isinstance(
|
||||
credit["login"], (str, github.NamedUser.NamedUser)
|
||||
), credit["login"]
|
||||
assert isinstance(credit["type"], str), credit["type"]
|
||||
else:
|
||||
assert isinstance(credit.login, str), credit.login
|
||||
assert isinstance(credit.type, str), credit.type
|
||||
|
||||
@staticmethod
|
||||
def _to_github_dict(credit: Credit) -> SimpleCredit:
|
||||
assert isinstance(credit, (dict, RepositoryAdvisoryCredit)), credit
|
||||
if isinstance(credit, dict):
|
||||
assert "login" in credit, credit
|
||||
assert "type" in credit, credit
|
||||
assert isinstance(
|
||||
credit["login"], (str, github.NamedUser.NamedUser)
|
||||
), credit["login"]
|
||||
login = credit["login"]
|
||||
if isinstance(login, github.NamedUser.NamedUser):
|
||||
login = login.login
|
||||
return {
|
||||
"login": login,
|
||||
"type": credit["type"],
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"login": credit.login,
|
||||
"type": credit.type,
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import github.GithubObject
|
||||
import github.NamedUser
|
||||
|
||||
|
||||
class RepositoryAdvisoryCreditDetailed(github.GithubObject.NonCompletableGithubObject):
|
||||
"""
|
||||
This class represents a credit that is assigned to a SecurityAdvisory.
|
||||
The reference can be found here https://docs.github.com/en/rest/security-advisories/repository-advisories
|
||||
"""
|
||||
|
||||
@property
|
||||
def state(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._state.value
|
||||
|
||||
@property
|
||||
def type(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._type.value
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
@property
|
||||
def user(self) -> "github.NamedUser.NamedUser":
|
||||
"""
|
||||
:type: :class:`github.NamedUser.NamedUser`
|
||||
"""
|
||||
return self._user.value
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _initAttributes(self):
|
||||
self._state = github.GithubObject.NotSet
|
||||
self._type = github.GithubObject.NotSet
|
||||
self._user = github.GithubObject.NotSet
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _useAttributes(self, attributes):
|
||||
if "state" in attributes: # pragma no branch
|
||||
self._state = self._makeStringAttribute(attributes["state"])
|
||||
if "type" in attributes: # pragma no branch
|
||||
self._type = self._makeStringAttribute(attributes["type"])
|
||||
if "user" in attributes: # pragma no branch
|
||||
self._user = self._makeClassAttribute(
|
||||
github.NamedUser.NamedUser, attributes["user"]
|
||||
)
|
||||
@@ -0,0 +1,187 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import typing
|
||||
from typing import List
|
||||
|
||||
import github.GithubObject
|
||||
import github.RepositoryAdvisoryVulnerabilityPackage
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
# TypedDict is only available in Python 3.8 and later
|
||||
class SimpleAdvisoryVulnerabilityPackage(typing.TypedDict):
|
||||
"""
|
||||
A simple package in an advisory.
|
||||
"""
|
||||
|
||||
ecosystem: str
|
||||
name: typing.Optional[str] # TODO: Python 3.11 make 'NotRequired'
|
||||
|
||||
class SimpleAdvisoryVulnerability(typing.TypedDict):
|
||||
"""
|
||||
A simple vulnerability in a security advisory.
|
||||
"""
|
||||
|
||||
package: SimpleAdvisoryVulnerabilityPackage
|
||||
patched_versions: typing.Optional[str] # TODO: Python 3.11 make 'NotRequired'
|
||||
vulnerable_functions: typing.Optional[
|
||||
List[str]
|
||||
] # TODO: Python 3.11 make 'NotRequired'
|
||||
vulnerable_version_range: typing.Optional[
|
||||
str
|
||||
] # TODO: Python 3.11 make 'NotRequired'
|
||||
|
||||
else:
|
||||
SimpleAdvisoryVulnerabilityPackage = typing.Dict[str, typing.Any]
|
||||
SimpleAdvisoryVulnerability = typing.Dict[str, typing.Any]
|
||||
|
||||
AdvisoryVulnerability = typing.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) -> typing.Optional[List[str]]:
|
||||
"""
|
||||
:type: list of string
|
||||
"""
|
||||
return self._vulnerable_functions.value
|
||||
|
||||
@property
|
||||
def vulnerable_version_range(self) -> typing.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,
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
############################ 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 Optional
|
||||
|
||||
import github.GithubObject
|
||||
|
||||
|
||||
class RepositoryAdvisoryVulnerabilityPackage(
|
||||
github.GithubObject.NonCompletableGithubObject
|
||||
):
|
||||
"""
|
||||
This class represents an identifier for 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 ecosystem(self) -> str:
|
||||
"""
|
||||
:type: string
|
||||
"""
|
||||
return self._ecosystem.value
|
||||
|
||||
@property
|
||||
def name(self) -> Optional[str]:
|
||||
"""
|
||||
:type: string or None
|
||||
"""
|
||||
return self._name.value
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _initAttributes(self):
|
||||
self._ecosystem = github.GithubObject.NotSet
|
||||
self._name = github.GithubObject.NotSet
|
||||
|
||||
# noinspection PyPep8Naming
|
||||
def _useAttributes(self, attributes):
|
||||
if "ecosystem" in attributes: # pragma no branch
|
||||
self._ecosystem = self._makeStringAttribute(attributes["ecosystem"])
|
||||
if "name" in attributes: # pragma no branch
|
||||
self._name = self._makeStringAttribute(attributes["name"])
|
||||
@@ -6,8 +6,16 @@
|
||||
# Copyright 2014 Thialfihar <thi@thialfihar.org> #
|
||||
# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
|
||||
# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
|
||||
# Copyright 2018 Yossarian King <yggy@blackbirdinteractive.com> #
|
||||
# Copyright 2018 sfdye <tsfdye@gmail.com> #
|
||||
# Copyright 2018 bbi-yggy <yossarian@blackbirdinteractive.com> #
|
||||
# Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2020 Isac Souza <isouza@daitan.com> #
|
||||
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2020 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2021 karsten-wagner <39054096+karsten-wagner@users.noreply.github.com>#
|
||||
# Copyright 2022 Gabriele Oliaro <ict@gabrieleoliaro.it> #
|
||||
# Copyright 2023 Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com> #
|
||||
# #
|
||||
# This file is part of PyGithub. #
|
||||
# http://pygithub.readthedocs.io/ #
|
||||
@@ -42,21 +50,25 @@ types = {
|
||||
"string",
|
||||
None,
|
||||
'self._makeStringAttribute(attributes["' + attributeName + '"])',
|
||||
"str",
|
||||
),
|
||||
"int": (
|
||||
"integer",
|
||||
None,
|
||||
'self._makeIntAttribute(attributes["' + attributeName + '"])',
|
||||
"int",
|
||||
),
|
||||
"bool": (
|
||||
"bool",
|
||||
None,
|
||||
'self._makeBoolAttribute(attributes["' + attributeName + '"])',
|
||||
"bool",
|
||||
),
|
||||
"datetime": (
|
||||
"datetime.datetime",
|
||||
"str",
|
||||
'self._makeDatetimeAttribute(attributes["' + attributeName + '"])',
|
||||
"datetime.datetime",
|
||||
),
|
||||
"class": (
|
||||
":class:`" + attributeClassType + "`",
|
||||
@@ -66,10 +78,16 @@ types = {
|
||||
+ ', attributes["'
|
||||
+ attributeName
|
||||
+ '"])',
|
||||
attributeClassType,
|
||||
),
|
||||
}
|
||||
|
||||
attributeDocType, attributeAssertType, attributeValue = types[attributeType]
|
||||
attributeDocType, attributeAssertType, attributeValue, attributeClassType = types[
|
||||
attributeType
|
||||
]
|
||||
if attributeType == "class":
|
||||
# Wrap in quotes to avoid an explicit import requirement which can cause circular import errors
|
||||
attributeClassType = f"'{attributeClassType}'"
|
||||
|
||||
|
||||
fileName = os.path.join("github", className + ".py")
|
||||
@@ -101,7 +119,9 @@ while not added:
|
||||
):
|
||||
if not isProperty:
|
||||
newLines.append(" @property")
|
||||
newLines.append(" def " + attributeName + "(self):")
|
||||
newLines.append(
|
||||
" def " + attributeName + "(self) -> " + attributeClassType + ":"
|
||||
)
|
||||
newLines.append(' """')
|
||||
newLines.append(" :type: " + attributeDocType)
|
||||
newLines.append(' """')
|
||||
|
||||
+19
-5
@@ -6,6 +6,10 @@
|
||||
# Copyright 2014 Vincent Jacques <vincent@vincent-jacques.net> #
|
||||
# Copyright 2016 Peter Buckley <dx-pbuckley@users.noreply.github.com> #
|
||||
# Copyright 2018 sfdye <tsfdye@gmail.com> #
|
||||
# Copyright 2019 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2019 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# Copyright 2020 Steve Kowalik <steven@wedontsleep.org> #
|
||||
# Copyright 2020 Wan Liuyang <tsfdye@gmail.com> #
|
||||
# #
|
||||
# This file is part of PyGithub. #
|
||||
# http://pygithub.readthedocs.io/ #
|
||||
@@ -60,9 +64,11 @@ def generateLicenseSection(filename):
|
||||
|
||||
def listContributors(filename):
|
||||
contributors = set()
|
||||
for line in subprocess.check_output(
|
||||
["git", "log", "--format=format:%ad %an <%ae>", "--date=short", "--", filename]
|
||||
).split("\n"):
|
||||
result = subprocess.check_output(
|
||||
["git", "log", "--format=format:%ad %an <%ae>", "--date=short", "--", filename],
|
||||
text=True,
|
||||
)
|
||||
for line in result.split("\n"):
|
||||
year = line[0:4]
|
||||
name = line[11:]
|
||||
contributors.add((year, name))
|
||||
@@ -126,7 +132,7 @@ class StandardHeader:
|
||||
|
||||
bodyLines = extractBodyLines(lines)
|
||||
|
||||
if len(bodyLines) and bodyLines[0] != "" > 0:
|
||||
if len(bodyLines) > 0 and bodyLines[0] != "":
|
||||
newLines.append("")
|
||||
newLines += bodyLines
|
||||
|
||||
@@ -141,10 +147,18 @@ def findHeadersAndFiles():
|
||||
dirs.remove("developer.github.com")
|
||||
if "build" in dirs:
|
||||
dirs.remove("build")
|
||||
if ".tox" in dirs:
|
||||
dirs.remove(".tox")
|
||||
if ".venv" in dirs:
|
||||
dirs.remove(".venv")
|
||||
if "PyGithub.egg-info" in dirs:
|
||||
dirs.remove("PyGithub.egg-info")
|
||||
|
||||
for filename in files:
|
||||
fullname = os.path.join(root, filename)
|
||||
if filename.endswith(".py"):
|
||||
if filename == "GithubCredentials.py":
|
||||
pass
|
||||
elif filename.endswith(".py"):
|
||||
yield (PythonHeader(), fullname)
|
||||
elif filename in ["COPYING", "COPYING.LESSER"]:
|
||||
pass
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
https
|
||||
PATCH
|
||||
api.github.com
|
||||
None
|
||||
/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
|
||||
{"credits": [{"login": "octocat", "type": "analyst"}, {"login": "JLLeitschuh", "type": "reporter"}]}
|
||||
200
|
||||
[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 20:49:25 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"752c50ea4418d5a955c86978a94775b8963dba736b2e51ee34e8f219d61062cf"'), ('Last-Modified', 'Thu, 30 Mar 2023 19:31:33 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4862'), ('X-RateLimit-Reset', '1680209691'), ('X-RateLimit-Used', '138'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'CF93:20BD:172867:2FBB1E:6425F5D4')]
|
||||
{"ghsa_id":"GHSA-wmmh-r9w4-hpxx","cve_id":"CVE-2023-00000","url":"https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx","html_url":"https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wmmh-r9w4-hpxx","summary":"A test creating a GHSA via the API","description":"This is a detailed description of this advisories impact and patches.","severity":"high","author":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"publisher":null,"identifiers":[{"value":"GHSA-wmmh-r9w4-hpxx","type":"GHSA"},{"value":"CVE-2023-00000","type":"CVE"}],"state":"draft","created_at":"2023-03-28T21:41:40Z","updated_at":"2023-03-30T19:31:33Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"a-package"},"vulnerable_version_range":">= 1.0.2","patched_versions":"1.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":"CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H","score":7.6},"cwes":[{"cwe_id":"CWE-400","name":"Uncontrolled Resource Consumption"},{"cwe_id":"CWE-501","name":"Trust Boundary Violation"}],"cwe_ids":["CWE-400","CWE-501"],"credits":[{"login":"octocat","type":"analyst"},{"login":"JLLeitschuh","type":"reporter"}],"credits_detailed":[{"user":{"login":"octocat","id":583231,"node_id":"MDQ6VXNlcjU4MzIzMQ==","avatar_url":"https://avatars.githubusercontent.com/u/583231?v=4","gravatar_id":"","url":"https://api.github.com/users/octocat","html_url":"https://github.com/octocat","followers_url":"https://api.github.com/users/octocat/followers","following_url":"https://api.github.com/users/octocat/following{/other_user}","gists_url":"https://api.github.com/users/octocat/gists{/gist_id}","starred_url":"https://api.github.com/users/octocat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/octocat/subscriptions","organizations_url":"https://api.github.com/users/octocat/orgs","repos_url":"https://api.github.com/users/octocat/repos","events_url":"https://api.github.com/users/octocat/events{/privacy}","received_events_url":"https://api.github.com/users/octocat/received_events","type":"User","site_admin":false},"type":"analyst","state":"pending"},{"user":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"type":"reporter","state":"accepted"}]}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
https
|
||||
PATCH
|
||||
api.github.com
|
||||
None
|
||||
/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
|
||||
{"credits": []}
|
||||
200
|
||||
[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 21:42:30 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"f4a77dc80164dd9e7a1f483b94c3db7ccbcbbccb996c1ed3d394cddf90b4d591"'), ('Last-Modified', 'Thu, 30 Mar 2023 19:31:33 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4923'), ('X-RateLimit-Reset', '1680213302'), ('X-RateLimit-Used', '77'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EAFF:0324:7AA77E8:FB2E11E:64260245')]
|
||||
{"ghsa_id":"GHSA-wmmh-r9w4-hpxx","cve_id":"CVE-2023-00000","url":"https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx","html_url":"https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wmmh-r9w4-hpxx","summary":"A test creating a GHSA via the API","description":"This is a detailed description of this advisories impact and patches.","severity":"high","author":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"publisher":null,"identifiers":[{"value":"GHSA-wmmh-r9w4-hpxx","type":"GHSA"},{"value":"CVE-2023-00000","type":"CVE"}],"state":"draft","created_at":"2023-03-28T21:41:40Z","updated_at":"2023-03-30T19:31:33Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"a-package"},"vulnerable_version_range":">= 1.0.2","patched_versions":"1.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":"CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H","score":7.6},"cwes":[{"cwe_id":"CWE-400","name":"Uncontrolled Resource Consumption"},{"cwe_id":"CWE-501","name":"Trust Boundary Violation"}],"cwe_ids":["CWE-400","CWE-501"],"credits":[],"credits_detailed":[]}
|
||||
|
||||
https
|
||||
PATCH
|
||||
api.github.com
|
||||
None
|
||||
/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
|
||||
{"credits": [{"login": "octocat", "type": "sponsor"}, {"login": "JLLeitschuh", "type": "reporter"}]}
|
||||
200
|
||||
[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 21:42:30 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"6f198359a2107c042d58ecf72395d46274b3b12337f85384a4019b616c62a67a"'), ('Last-Modified', 'Thu, 30 Mar 2023 19:31:33 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4922'), ('X-RateLimit-Reset', '1680213302'), ('X-RateLimit-Used', '78'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'EB00:475B:295BC8:551DDE:64260246')]
|
||||
{"ghsa_id":"GHSA-wmmh-r9w4-hpxx","cve_id":"CVE-2023-00000","url":"https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx","html_url":"https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wmmh-r9w4-hpxx","summary":"A test creating a GHSA via the API","description":"This is a detailed description of this advisories impact and patches.","severity":"high","author":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"publisher":null,"identifiers":[{"value":"GHSA-wmmh-r9w4-hpxx","type":"GHSA"},{"value":"CVE-2023-00000","type":"CVE"}],"state":"draft","created_at":"2023-03-28T21:41:40Z","updated_at":"2023-03-30T19:31:33Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"a-package"},"vulnerable_version_range":">= 1.0.2","patched_versions":"1.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":"CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H","score":7.6},"cwes":[{"cwe_id":"CWE-400","name":"Uncontrolled Resource Consumption"},{"cwe_id":"CWE-501","name":"Trust Boundary Violation"}],"cwe_ids":["CWE-400","CWE-501"],"credits":[{"login":"octocat","type":"sponsor"},{"login":"JLLeitschuh","type":"reporter"}],"credits_detailed":[{"user":{"login":"octocat","id":583231,"node_id":"MDQ6VXNlcjU4MzIzMQ==","avatar_url":"https://avatars.githubusercontent.com/u/583231?v=4","gravatar_id":"","url":"https://api.github.com/users/octocat","html_url":"https://github.com/octocat","followers_url":"https://api.github.com/users/octocat/followers","following_url":"https://api.github.com/users/octocat/following{/other_user}","gists_url":"https://api.github.com/users/octocat/gists{/gist_id}","starred_url":"https://api.github.com/users/octocat/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/octocat/subscriptions","organizations_url":"https://api.github.com/users/octocat/orgs","repos_url":"https://api.github.com/users/octocat/repos","events_url":"https://api.github.com/users/octocat/events{/privacy}","received_events_url":"https://api.github.com/users/octocat/received_events","type":"User","site_admin":false},"type":"sponsor","state":"pending"},{"user":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"type":"reporter","state":"accepted"}]}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
https
|
||||
PATCH
|
||||
api.github.com
|
||||
None
|
||||
/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx
|
||||
{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'}
|
||||
{"credits": []}
|
||||
200
|
||||
[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 19:04:19 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"a5b5fadc5ecef7df034508971debefa3dac9324c6dbe6a06e399026c5ff5ec3e"'), ('Last-Modified', 'Tue, 28 Mar 2023 21:41:40 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4984'), ('X-RateLimit-Reset', '1680206007'), ('X-RateLimit-Used', '16'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'D88C:0FC0:1C7A795:3A9AF22:6425DD32')]
|
||||
{"ghsa_id":"GHSA-wmmh-r9w4-hpxx","cve_id":"CVE-2050-00000","url":"https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx","html_url":"https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wmmh-r9w4-hpxx","summary":"A test creating a GHSA via the API","description":"This is a detailed description of this advisories impact and patches.","severity":"high","author":{"login":"JLLeitschuh","id":1323708,"node_id":"MDQ6VXNlcjEzMjM3MDg=","avatar_url":"https://avatars.githubusercontent.com/u/1323708?v=4","gravatar_id":"","url":"https://api.github.com/users/JLLeitschuh","html_url":"https://github.com/JLLeitschuh","followers_url":"https://api.github.com/users/JLLeitschuh/followers","following_url":"https://api.github.com/users/JLLeitschuh/following{/other_user}","gists_url":"https://api.github.com/users/JLLeitschuh/gists{/gist_id}","starred_url":"https://api.github.com/users/JLLeitschuh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JLLeitschuh/subscriptions","organizations_url":"https://api.github.com/users/JLLeitschuh/orgs","repos_url":"https://api.github.com/users/JLLeitschuh/repos","events_url":"https://api.github.com/users/JLLeitschuh/events{/privacy}","received_events_url":"https://api.github.com/users/JLLeitschuh/received_events","type":"User","site_admin":false},"publisher":null,"identifiers":[{"value":"GHSA-wmmh-r9w4-hpxx","type":"GHSA"},{"value":"CVE-2050-00000","type":"CVE"}],"state":"draft","created_at":"2023-03-28T21:41:40Z","updated_at":"2023-03-28T21:41:40Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"a-package"},"vulnerable_version_range":">= 1.0.2","patched_versions":"1.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":"CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H","score":7.6},"cwes":[{"cwe_id":"CWE-400","name":"Uncontrolled Resource Consumption"},{"cwe_id":"CWE-501","name":"Trust Boundary Violation"}],"cwe_ids":["CWE-400","CWE-501"],"credits":[],"credits_detailed":[]}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,358 @@
|
||||
############################ 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/>. #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
import datetime
|
||||
|
||||
import github.RepositoryAdvisory
|
||||
|
||||
from . import Framework
|
||||
|
||||
|
||||
class RepositoryAdvisory(Framework.TestCase):
|
||||
advisory: github.RepositoryAdvisory.RepositoryAdvisory
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.repo = self.g.get_user().get_repo("security-research")
|
||||
self.advisory = self.repo.get_repository_advisory("GHSA-wmmh-r9w4-hpxx")
|
||||
self.advisory.clear_credits()
|
||||
self.advisory.offer_credit("octocat", "analyst")
|
||||
|
||||
def testAttributes(self):
|
||||
self.assertEqual(self.advisory.author.login, "JLLeitschuh")
|
||||
self.assertEqual(self.advisory.closed_at, None)
|
||||
self.assertEqual(
|
||||
self.advisory.created_at, datetime.datetime(2023, 3, 28, 21, 41, 40)
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits, lambda e: (e.login, e.type), [("octocat", "analyst")]
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits_detailed,
|
||||
lambda e: (e.user.login, e.type),
|
||||
[("octocat", "analyst")],
|
||||
)
|
||||
self.assertEqual(self.advisory.cve_id, "CVE-2023-00000")
|
||||
self.assertListEqual(self.advisory.cwe_ids, ["CWE-400", "CWE-501"])
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.cwes,
|
||||
lambda e: (e.cwe_id, e.name),
|
||||
[
|
||||
("CWE-400", "Uncontrolled Resource Consumption"),
|
||||
("CWE-501", "Trust Boundary Violation"),
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
self.advisory.description,
|
||||
"This is a detailed description of this advisories impact and patches.",
|
||||
)
|
||||
self.assertEqual(self.advisory.ghsa_id, "GHSA-wmmh-r9w4-hpxx")
|
||||
self.assertEqual(
|
||||
self.advisory.html_url,
|
||||
"https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wmmh-r9w4-hpxx",
|
||||
)
|
||||
self.assertEqual(self.advisory.published_at, None)
|
||||
self.assertEqual(self.advisory.severity, "high")
|
||||
self.assertEqual(self.advisory.state, "draft")
|
||||
self.assertEqual(self.advisory.summary, "A test creating a GHSA via the API")
|
||||
self.assertEqual(
|
||||
self.advisory.updated_at, datetime.datetime(2023, 3, 30, 19, 31, 33)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.advisory.url,
|
||||
"https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx",
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[(("npm", "a-package"), "1.0.5", ["function-name"], ">= 1.0.2")],
|
||||
)
|
||||
self.assertEqual(self.advisory.withdrawn_at, None)
|
||||
|
||||
def testRemoveCredit(self):
|
||||
self.advisory.revoke_credit("octocat")
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits,
|
||||
lambda e: e.login,
|
||||
[],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits_detailed,
|
||||
lambda e: e.user.login,
|
||||
[],
|
||||
)
|
||||
|
||||
def testOfferCredit(self):
|
||||
self.advisory.offer_credit("JLLeitschuh", "reporter")
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits,
|
||||
lambda e: e.login,
|
||||
["octocat", "JLLeitschuh"],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits_detailed,
|
||||
lambda e: e.user.login,
|
||||
["octocat", "JLLeitschuh"],
|
||||
)
|
||||
|
||||
def testOfferCredits(self):
|
||||
self.advisory.clear_credits()
|
||||
self.advisory.offer_credits(
|
||||
[
|
||||
{"login": "octocat", "type": "sponsor"},
|
||||
{"login": "JLLeitschuh", "type": "reporter"},
|
||||
]
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
self.advisory.credits_detailed,
|
||||
lambda e: (e.user.login, e.type),
|
||||
[("octocat", "sponsor"), ("JLLeitschuh", "reporter")],
|
||||
)
|
||||
|
||||
def testRepositoryWithNoAdvisories(self):
|
||||
repo = self.g.get_user().get_repo("PyGithub")
|
||||
self.assertListKeyEqual(
|
||||
repo.get_repository_advisories(),
|
||||
lambda e: e.ghsa_id,
|
||||
[],
|
||||
)
|
||||
|
||||
def testGetAdvisories(self):
|
||||
self.assertListKeyEqual(
|
||||
self.repo.get_repository_advisories(),
|
||||
lambda e: e.ghsa_id,
|
||||
[
|
||||
"GHSA-wmmh-r9w4-hpxx",
|
||||
"GHSA-wvgm-59wj-rh8h",
|
||||
"GHSA-22cq-8f5q-p5g2",
|
||||
"GHSA-7hfp-mpq6-2jhf",
|
||||
"GHSA-hfmw-fx2m-jj4c",
|
||||
"GHSA-rvp4-r3g6-8hxq",
|
||||
"GHSA-cm59-pr5q-cw85",
|
||||
"GHSA-vpcc-9rh2-8jfp",
|
||||
"GHSA-7fjx-657r-9r5h",
|
||||
"GHSA-22c6-wcjm-qfjg",
|
||||
"GHSA-5w9v-8x7x-rfqm",
|
||||
"GHSA-2r85-x9cf-8fcg",
|
||||
"GHSA-6m9h-r5m3-9r7f",
|
||||
"GHSA-f4jh-ww96-9h9j",
|
||||
"GHSA-j83w-7qr9-wv86",
|
||||
"GHSA-7gf3-89f6-823j",
|
||||
"GHSA-jpcm-4485-69p7",
|
||||
],
|
||||
)
|
||||
|
||||
def testCreateRepositoryAdvisory(self):
|
||||
repo = self.g.get_repo("JLLeitschuh/code-sandbox")
|
||||
advisory = repo.create_repository_advisory(
|
||||
"A test creating a GHSA via the API",
|
||||
"This is a detailed description of this advisories impact and patches.",
|
||||
"high",
|
||||
"CVE-2000-00000",
|
||||
vulnerabilities=[
|
||||
{
|
||||
"package": {"ecosystem": "npm", "name": "b-package"},
|
||||
"vulnerable_version_range": "<=4.0.4",
|
||||
"patched_versions": "4.0.5",
|
||||
"vulnerable_functions": ["function-name"],
|
||||
}
|
||||
],
|
||||
cwe_ids=["CWE-401", "CWE-502"],
|
||||
credits=[
|
||||
{"login": "octocat", "type": "analyst"},
|
||||
{"login": "JLLeitschuh", "type": "reporter"},
|
||||
],
|
||||
)
|
||||
self.assertEqual(advisory.ghsa_id, "GHSA-g45c-2crh-4xmp")
|
||||
self.assertEqual(advisory.summary, "A test creating a GHSA via the API")
|
||||
self.assertEqual(
|
||||
advisory.description,
|
||||
"This is a detailed description of this advisories impact and patches.",
|
||||
)
|
||||
self.assertEqual(advisory.severity, "high")
|
||||
self.assertEqual(advisory.cve_id, "CVE-2000-00000")
|
||||
self.assertListKeyEqual(
|
||||
advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[(("npm", "b-package"), "4.0.5", ["function-name"], "<=4.0.4")],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.cwe_ids,
|
||||
lambda e: e,
|
||||
["CWE-401", "CWE-502"],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.credits_detailed,
|
||||
lambda e: (e.user.login, e.type),
|
||||
[("octocat", "analyst"), ("JLLeitschuh", "reporter")],
|
||||
)
|
||||
|
||||
def testUpdateRepositoryAdvisory(self):
|
||||
repo = self.g.get_repo("JLLeitschuh/code-sandbox")
|
||||
advisory = repo.get_repository_advisory("GHSA-g45c-2crh-4xmp")
|
||||
advisory.edit(
|
||||
summary="A test updating a GHSA via the API",
|
||||
description="This is an updated detailed description of this advisories impact and patches.",
|
||||
severity_or_cvss_vector_string="low",
|
||||
cve_id="CVE-2000-00001",
|
||||
vulnerabilities=[
|
||||
{
|
||||
"package": {"ecosystem": "npm", "name": "c-package"},
|
||||
"vulnerable_version_range": "<=4.0.6",
|
||||
"patched_versions": "4.0.7",
|
||||
"vulnerable_functions": ["function-name-a"],
|
||||
}
|
||||
],
|
||||
cwe_ids=["CWE-402", "CWE-500"],
|
||||
credits=[
|
||||
{"login": "octocat", "type": "sponsor"},
|
||||
{"login": "JLLeitschuh", "type": "reporter"},
|
||||
],
|
||||
)
|
||||
self.assertEqual(advisory.ghsa_id, "GHSA-g45c-2crh-4xmp")
|
||||
self.assertEqual(advisory.summary, "A test updating a GHSA via the API")
|
||||
self.assertEqual(
|
||||
advisory.description,
|
||||
"This is an updated detailed description of this advisories impact and patches.",
|
||||
)
|
||||
self.assertEqual(advisory.severity, "low")
|
||||
self.assertEqual(advisory.cve_id, "CVE-2000-00001")
|
||||
self.assertListKeyEqual(
|
||||
advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[(("npm", "c-package"), "4.0.7", ["function-name-a"], "<=4.0.6")],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.cwe_ids,
|
||||
lambda e: e,
|
||||
["CWE-402", "CWE-500"],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.credits_detailed,
|
||||
lambda e: (e.user.login, e.type),
|
||||
[("octocat", "sponsor"), ("JLLeitschuh", "reporter")],
|
||||
)
|
||||
|
||||
def testUpdateSingleFieldDoesNotRemoveOtherFields(self):
|
||||
repo = self.g.get_repo("JLLeitschuh/code-sandbox")
|
||||
advisory = repo.create_repository_advisory(
|
||||
"A test editing a GHSA via the API with only a single manipulation",
|
||||
"This is a detailed description of this advisories impact and patches.",
|
||||
"high",
|
||||
"CVE-2000-00000",
|
||||
vulnerabilities=[
|
||||
{
|
||||
"package": {"ecosystem": "npm", "name": "b-package"},
|
||||
"vulnerable_version_range": "<=4.0.4",
|
||||
"patched_versions": "4.0.5",
|
||||
"vulnerable_functions": ["function-name"],
|
||||
}
|
||||
],
|
||||
cwe_ids=["CWE-401", "CWE-502"],
|
||||
credits=[
|
||||
{"login": "octocat", "type": "analyst"},
|
||||
{"login": "JLLeitschuh", "type": "reporter"},
|
||||
],
|
||||
)
|
||||
advisory.edit(description="A modified description")
|
||||
self.assertEqual(advisory.ghsa_id, "GHSA-4wwp-8jp9-9233")
|
||||
self.assertEqual(
|
||||
advisory.summary,
|
||||
"A test editing a GHSA via the API with only a single manipulation",
|
||||
)
|
||||
self.assertEqual(advisory.description, "A modified description")
|
||||
self.assertEqual(advisory.severity, "high")
|
||||
self.assertEqual(advisory.cve_id, "CVE-2000-00000")
|
||||
self.assertListKeyEqual(
|
||||
advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[(("npm", "b-package"), "4.0.5", ["function-name"], "<=4.0.4")],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.cwe_ids,
|
||||
lambda e: e,
|
||||
["CWE-401", "CWE-502"],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.credits_detailed,
|
||||
lambda e: (e.user.login, e.type),
|
||||
[("octocat", "analyst"), ("JLLeitschuh", "reporter")],
|
||||
)
|
||||
|
||||
def testAddVulnerability(self):
|
||||
repo = self.g.get_repo("JLLeitschuh/code-sandbox")
|
||||
advisory = repo.create_repository_advisory(
|
||||
summary="A test creating a GHSA via the API adding and removing vulnerabilities",
|
||||
description="Simple description",
|
||||
severity_or_cvss_vector_string="low",
|
||||
)
|
||||
advisory.add_vulnerability(ecosystem="maven")
|
||||
self.assertListKeyEqual(
|
||||
advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[(("maven", None), None, [], None)],
|
||||
)
|
||||
advisory.add_vulnerability(
|
||||
ecosystem="npm",
|
||||
package_name="b-package",
|
||||
vulnerable_version_range="<=4.0.9",
|
||||
patched_versions="4.0.10",
|
||||
vulnerable_functions=["function-name-c"],
|
||||
)
|
||||
self.assertListKeyEqual(
|
||||
advisory.vulnerabilities,
|
||||
lambda e: (
|
||||
(e.package.ecosystem, e.package.name),
|
||||
e.patched_versions,
|
||||
e.vulnerable_functions,
|
||||
e.vulnerable_version_range,
|
||||
),
|
||||
[
|
||||
(("maven", None), None, [], None),
|
||||
(("npm", "b-package"), "4.0.10", ["function-name-c"], "<=4.0.9"),
|
||||
],
|
||||
)
|
||||
Reference in New Issue
Block a user