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`.
|
||||
See :ref:`the docs <config-copyright>` for further detail.
|
||||
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
|
||||
----------
|
||||
|
@ -249,6 +249,34 @@ There is also an :rst:role:`index` role to generate index entries.
|
||||
|
||||
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
|
||||
|
||||
A reference to a Python Enhancement Proposal. This generates appropriate
|
||||
|
@ -53,6 +53,10 @@ default_settings: dict[str, Any] = {
|
||||
'image_loading': 'link',
|
||||
'embed_stylesheet': False,
|
||||
'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_references': None,
|
||||
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
||||
|
@ -196,6 +196,94 @@ class AnyXRefRole(XRefRole):
|
||||
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):
|
||||
def run(self) -> tuple[list[Node], list[system_message]]:
|
||||
target_id = 'index-%s' % self.env.new_serialno('index')
|
||||
@ -454,12 +542,17 @@ specific_docroles: dict[str, RoleFunction] = {
|
||||
'download': XRefRole(nodeclass=addnodes.download_reference),
|
||||
# links to anything
|
||||
'any': AnyXRefRole(warn_dangling=True),
|
||||
# external links
|
||||
'cve': CVE(),
|
||||
'cwe': CWE(),
|
||||
'pep': PEP(),
|
||||
'rfc': RFC(),
|
||||
# emphasised things
|
||||
'guilabel': GUILabel(),
|
||||
'menuselection': MenuSelection(),
|
||||
'file': EmphasizedLiteral(),
|
||||
'samp': EmphasizedLiteral(),
|
||||
# other
|
||||
'abbr': Abbreviation(),
|
||||
'manpage': Manpage(),
|
||||
}
|
||||
|
@ -160,6 +160,74 @@ def get_verifier(verify, verify_re):
|
||||
@pytest.mark.parametrize(
|
||||
('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
|
||||
'verify',
|
||||
|
Loading…
Reference in New Issue
Block a user