mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add CVE and CWE roles (#11781)
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
parent
f7fa020cc2
commit
09ab6edde5
@ -59,6 +59,9 @@ Features added
|
|||||||
such as :py:mod:`time` or :py:mod:`datetime` in :file:`conf.py`.
|
such as :py:mod:`time` or :py:mod:`datetime` in :file:`conf.py`.
|
||||||
See :ref:`the docs <config-copyright>` for further detail.
|
See :ref:`the docs <config-copyright>` for further detail.
|
||||||
Patch by Adam Turner.
|
Patch by Adam Turner.
|
||||||
|
* #11781: Add roles for referencing CVEs (:rst:role:`:cve: <cve>`)
|
||||||
|
and CWEs (:rst:role:`:cwe: <cwe>`).
|
||||||
|
Patch by Hugo van Kemenade.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
@ -249,6 +249,34 @@ There is also an :rst:role:`index` role to generate index entries.
|
|||||||
|
|
||||||
The following roles generate external links:
|
The following roles generate external links:
|
||||||
|
|
||||||
|
.. rst:role:: cve
|
||||||
|
|
||||||
|
A reference to a `Common Vulnerabilities and Exposures`_ record.
|
||||||
|
This generates appropriate index entries.
|
||||||
|
The text "CVE *number*\ " is generated;
|
||||||
|
with a link to an online copy of the specified CVE.
|
||||||
|
You can link to a specific section by using ``:cve:`number#anchor```.
|
||||||
|
|
||||||
|
.. _Common Vulnerabilities and Exposures: https://www.cve.org/
|
||||||
|
|
||||||
|
For example: :cve:`2020-10735`
|
||||||
|
|
||||||
|
.. versionadded:: 8.1
|
||||||
|
|
||||||
|
.. rst:role:: cwe
|
||||||
|
|
||||||
|
A reference to a `Common Weakness Enumeration`_.
|
||||||
|
This generates appropriate index entries.
|
||||||
|
The text "CWE *number*\ " is generated; in the HTML output,
|
||||||
|
with a link to an online copy of the specified CWE.
|
||||||
|
You can link to a specific section by using ``:cwe:`number#anchor```.
|
||||||
|
|
||||||
|
.. _Common Weakness Enumeration: https://cwe.mitre.org/
|
||||||
|
|
||||||
|
For example: :cwe:`787`
|
||||||
|
|
||||||
|
.. versionadded:: 8.1
|
||||||
|
|
||||||
.. rst:role:: pep
|
.. rst:role:: pep
|
||||||
|
|
||||||
A reference to a Python Enhancement Proposal. This generates appropriate
|
A reference to a Python Enhancement Proposal. This generates appropriate
|
||||||
|
@ -53,6 +53,10 @@ default_settings: dict[str, Any] = {
|
|||||||
'image_loading': 'link',
|
'image_loading': 'link',
|
||||||
'embed_stylesheet': False,
|
'embed_stylesheet': False,
|
||||||
'cloak_email_addresses': True,
|
'cloak_email_addresses': True,
|
||||||
|
'cve_base_url': 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-',
|
||||||
|
'cve_references': None,
|
||||||
|
'cwe_base_url': 'https://cwe.mitre.org/data/definitions/',
|
||||||
|
'cwe_references': None,
|
||||||
'pep_base_url': 'https://peps.python.org/',
|
'pep_base_url': 'https://peps.python.org/',
|
||||||
'pep_references': None,
|
'pep_references': None,
|
||||||
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
||||||
|
@ -196,6 +196,94 @@ class AnyXRefRole(XRefRole):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class CVE(ReferenceRole):
|
||||||
|
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||||
|
target_id = f'index-{self.env.new_serialno("index")}'
|
||||||
|
entries = [
|
||||||
|
(
|
||||||
|
'single',
|
||||||
|
_('Common Vulnerabilities and Exposures; CVE %s') % self.target,
|
||||||
|
target_id,
|
||||||
|
'',
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
index = addnodes.index(entries=entries)
|
||||||
|
target = nodes.target('', '', ids=[target_id])
|
||||||
|
self.inliner.document.note_explicit_target(target)
|
||||||
|
|
||||||
|
try:
|
||||||
|
refuri = self.build_uri()
|
||||||
|
reference = nodes.reference(
|
||||||
|
'', '', internal=False, refuri=refuri, classes=['cve']
|
||||||
|
)
|
||||||
|
if self.has_explicit_title:
|
||||||
|
reference += nodes.strong(self.title, self.title)
|
||||||
|
else:
|
||||||
|
title = f'CVE {self.title}'
|
||||||
|
reference += nodes.strong(title, title)
|
||||||
|
except ValueError:
|
||||||
|
msg = self.inliner.reporter.error(
|
||||||
|
__('invalid CVE number %s') % self.target, line=self.lineno
|
||||||
|
)
|
||||||
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
||||||
|
return [prb], [msg]
|
||||||
|
|
||||||
|
return [index, target, reference], []
|
||||||
|
|
||||||
|
def build_uri(self) -> str:
|
||||||
|
base_url = self.inliner.document.settings.cve_base_url
|
||||||
|
ret = self.target.split('#', 1)
|
||||||
|
if len(ret) == 2:
|
||||||
|
return f'{base_url}{ret[0]}#{ret[1]}'
|
||||||
|
return f'{base_url}{ret[0]}'
|
||||||
|
|
||||||
|
|
||||||
|
class CWE(ReferenceRole):
|
||||||
|
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||||
|
target_id = f'index-{self.env.new_serialno("index")}'
|
||||||
|
entries = [
|
||||||
|
(
|
||||||
|
'single',
|
||||||
|
_('Common Weakness Enumeration; CWE %s') % self.target,
|
||||||
|
target_id,
|
||||||
|
'',
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
index = addnodes.index(entries=entries)
|
||||||
|
target = nodes.target('', '', ids=[target_id])
|
||||||
|
self.inliner.document.note_explicit_target(target)
|
||||||
|
|
||||||
|
try:
|
||||||
|
refuri = self.build_uri()
|
||||||
|
reference = nodes.reference(
|
||||||
|
'', '', internal=False, refuri=refuri, classes=['cwe']
|
||||||
|
)
|
||||||
|
if self.has_explicit_title:
|
||||||
|
reference += nodes.strong(self.title, self.title)
|
||||||
|
else:
|
||||||
|
title = f'CWE {self.title}'
|
||||||
|
reference += nodes.strong(title, title)
|
||||||
|
except ValueError:
|
||||||
|
msg = self.inliner.reporter.error(
|
||||||
|
__('invalid CWE number %s') % self.target, line=self.lineno
|
||||||
|
)
|
||||||
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
||||||
|
return [prb], [msg]
|
||||||
|
|
||||||
|
return [index, target, reference], []
|
||||||
|
|
||||||
|
def build_uri(self) -> str:
|
||||||
|
base_url = self.inliner.document.settings.cwe_base_url
|
||||||
|
ret = self.target.split('#', 1)
|
||||||
|
if len(ret) == 2:
|
||||||
|
return f'{base_url}{int(ret[0])}.html#{ret[1]}'
|
||||||
|
return f'{base_url}{int(ret[0])}.html'
|
||||||
|
|
||||||
|
|
||||||
class PEP(ReferenceRole):
|
class PEP(ReferenceRole):
|
||||||
def run(self) -> tuple[list[Node], list[system_message]]:
|
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||||
@ -454,12 +542,17 @@ specific_docroles: dict[str, RoleFunction] = {
|
|||||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||||
# links to anything
|
# links to anything
|
||||||
'any': AnyXRefRole(warn_dangling=True),
|
'any': AnyXRefRole(warn_dangling=True),
|
||||||
|
# external links
|
||||||
|
'cve': CVE(),
|
||||||
|
'cwe': CWE(),
|
||||||
'pep': PEP(),
|
'pep': PEP(),
|
||||||
'rfc': RFC(),
|
'rfc': RFC(),
|
||||||
|
# emphasised things
|
||||||
'guilabel': GUILabel(),
|
'guilabel': GUILabel(),
|
||||||
'menuselection': MenuSelection(),
|
'menuselection': MenuSelection(),
|
||||||
'file': EmphasizedLiteral(),
|
'file': EmphasizedLiteral(),
|
||||||
'samp': EmphasizedLiteral(),
|
'samp': EmphasizedLiteral(),
|
||||||
|
# other
|
||||||
'abbr': Abbreviation(),
|
'abbr': Abbreviation(),
|
||||||
'manpage': Manpage(),
|
'manpage': Manpage(),
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,74 @@ def get_verifier(verify, verify_re):
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
('type', 'rst', 'html_expected', 'latex_expected'),
|
('type', 'rst', 'html_expected', 'latex_expected'),
|
||||||
[
|
[
|
||||||
|
(
|
||||||
|
# cve role
|
||||||
|
'verify',
|
||||||
|
':cve:`2020-10735`',
|
||||||
|
(
|
||||||
|
'<p><span class="target" id="index-0"></span><a class="cve reference external" '
|
||||||
|
'href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735">'
|
||||||
|
'<strong>CVE 2020-10735</strong></a></p>'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'\\sphinxAtStartPar\n'
|
||||||
|
'\\index{Common Vulnerabilities and Exposures@\\spxentry{Common Vulnerabilities and Exposures}'
|
||||||
|
'!CVE 2020\\sphinxhyphen{}10735@\\spxentry{CVE 2020\\sphinxhyphen{}10735}}'
|
||||||
|
'\\sphinxhref{https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735}'
|
||||||
|
'{\\sphinxstylestrong{CVE 2020\\sphinxhyphen{}10735}}'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# cve role with anchor
|
||||||
|
'verify',
|
||||||
|
':cve:`2020-10735#id1`',
|
||||||
|
(
|
||||||
|
'<p><span class="target" id="index-0"></span><a class="cve reference external" '
|
||||||
|
'href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735#id1">'
|
||||||
|
'<strong>CVE 2020-10735#id1</strong></a></p>'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'\\sphinxAtStartPar\n'
|
||||||
|
'\\index{Common Vulnerabilities and Exposures@\\spxentry{Common Vulnerabilities and Exposures}'
|
||||||
|
'!CVE 2020\\sphinxhyphen{}10735\\#id1@\\spxentry{CVE 2020\\sphinxhyphen{}10735\\#id1}}'
|
||||||
|
'\\sphinxhref{https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735\\#id1}'
|
||||||
|
'{\\sphinxstylestrong{CVE 2020\\sphinxhyphen{}10735\\#id1}}'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# cwe role
|
||||||
|
'verify',
|
||||||
|
':cwe:`787`',
|
||||||
|
(
|
||||||
|
'<p><span class="target" id="index-0"></span><a class="cwe reference external" '
|
||||||
|
'href="https://cwe.mitre.org/data/definitions/787.html">'
|
||||||
|
'<strong>CWE 787</strong></a></p>'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'\\sphinxAtStartPar\n'
|
||||||
|
'\\index{Common Weakness Enumeration@\\spxentry{Common Weakness Enumeration}'
|
||||||
|
'!CWE 787@\\spxentry{CWE 787}}'
|
||||||
|
'\\sphinxhref{https://cwe.mitre.org/data/definitions/787.html}'
|
||||||
|
'{\\sphinxstylestrong{CWE 787}}'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# cwe role with anchor
|
||||||
|
'verify',
|
||||||
|
':cwe:`787#id1`',
|
||||||
|
(
|
||||||
|
'<p><span class="target" id="index-0"></span><a class="cwe reference external" '
|
||||||
|
'href="https://cwe.mitre.org/data/definitions/787.html#id1">'
|
||||||
|
'<strong>CWE 787#id1</strong></a></p>'
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'\\sphinxAtStartPar\n'
|
||||||
|
'\\index{Common Weakness Enumeration@\\spxentry{Common Weakness Enumeration}'
|
||||||
|
'!CWE 787\\#id1@\\spxentry{CWE 787\\#id1}}'
|
||||||
|
'\\sphinxhref{https://cwe.mitre.org/data/definitions/787.html\\#id1}'
|
||||||
|
'{\\sphinxstylestrong{CWE 787\\#id1}}'
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
# pep role
|
# pep role
|
||||||
'verify',
|
'verify',
|
||||||
|
Loading…
Reference in New Issue
Block a user