Repository navigation
Add optional CVE metadata for Security entries #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,6 +58,13 @@ | |
| ----------------------------------------------------------------------------- | ||
| Optional metadata: | ||
| * "cve" names the CVE identifier (e.g. "CVE-2026-12345") addressed | ||
| by the entry. It may only be used in the "Security" section. | ||
| ----------------------------------------------------------------------------- | ||
| The format of a "next" file is exactly the same, except that we're storing | ||
| four pieces of metadata in the filename instead of in the metadata section. | ||
| Those four pieces of metadata are: section, gh-issue, date, and nonce. | ||
|
|
@@ -88,12 +95,28 @@ | |
|
|
||
| root = None # Set by chdir_to_repo_root() | ||
| lowest_possible_gh_issue_number = 32426 | ||
| cve_section = 'Security' | ||
|
|
||
| _cve_re = re.compile(r'(?:CVE-)?(\d{4})-(\d{4,})', re.IGNORECASE | re.ASCII) | ||
|
|
||
|
|
||
| class BlurbError(RuntimeError): | ||
| pass | ||
|
|
||
|
|
||
| def normalize_cve(value: str, /) -> str | None: | ||
| """Return a CVE identifier in canonical "CVE-YYYY-NNNN" form. | ||
| Accepts a case-insensitive "CVE-" prefix, or none at all. | ||
| Returns None if the value isn't a valid CVE identifier. | ||
| """ | ||
| match = _cve_re.fullmatch(value.strip()) | ||
| if match is None: | ||
| return None | ||
| year, number = match.groups() | ||
| return f'CVE-{year}-{number}' | ||
|
|
||
|
|
||
| class Blurbs(list): | ||
| def parse( | ||
| self, | ||
|
|
@@ -168,6 +191,17 @@ def finish_entry() -> None: | |
| f'Invalid section {value!r}! You must use one of the predefined sections.' | ||
| ) | ||
|
|
||
| if key == 'cve': | ||
| cve = normalize_cve(value) | ||
| if cve is None: | ||
| throw( | ||
| f'Invalid CVE identifier: {value!r} (expected CVE-YYYY-NNNN)' | ||
| ) | ||
| metadata[key] = cve | ||
|
|
||
| if 'cve' in metadata and metadata.get('section') != cve_section: | ||
| throw(f"'cve:' may only be used in the {cve_section!r} section!") | ||
|
Comment on lines
+202
to
+203
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have sometimes included CVEs in non-security sections:
Should we not allow those? In those cases, should they have been under Security? |
||
|
|
||
| if 'gh-issue' not in metadata and 'bpo' not in metadata: | ||
| throw("'gh-issue:' or 'bpo:' must be specified in the metadata!") | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -95,14 +95,19 @@ def prnt(msg: str = '', /): | |||||||||
| prnt(section) | ||||||||||
| prnt('-' * len(section)) | ||||||||||
| prnt() | ||||||||||
| prefix = '' | ||||||||||
| if metadata.get('gh-issue'): | ||||||||||
| issue_number = metadata['gh-issue'] | ||||||||||
| if int(issue_number): | ||||||||||
| body = f'gh-{issue_number}: {body}' | ||||||||||
| prefix = f'gh-{issue_number}' | ||||||||||
| elif metadata.get('bpo'): | ||||||||||
| issue_number = metadata['bpo'] | ||||||||||
| if int(issue_number): | ||||||||||
| body = f'bpo-{issue_number}: {body}' | ||||||||||
| prefix = f'bpo-{issue_number}' | ||||||||||
| if cve := metadata.get('cve'): | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bit of whitespace
Suggested change
|
||||||||||
| prefix = f'{prefix}, {cve}' if prefix else cve | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's do something like this to use the Sphinx https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-cve
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shall we put the CVE before the gh-number? That's what we did at https://blog.python.org/2026/10/python-31022-31117/ and I think the CVE is more interesting for readers?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't add the role, it would break 3.11. I have a PR in CPython to add it there, like we do for GitHub issues. |
||||||||||
| if prefix: | ||||||||||
| body = f'{prefix}: {body}' | ||||||||||
|
|
||||||||||
| body = f'- {body}' | ||||||||||
| text = textwrap_body(body, subsequent_indent=' ') | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .. cve: CVE-2025-12345 | ||
| .. gh-issue: 135661 | ||
| .. section: Library | ||
|
|
||
| This is an invalid blurb. A CVE may only be given in the Security section. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .. cve: CVE-25-1 | ||
| .. gh-issue: 135661 | ||
| .. section: Security | ||
|
|
||
| This is an invalid blurb. "CVE-25-1" is not a valid CVE identifier. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| .. cve: cve-2025-12345 | ||
| .. date: 2026-10-14 | ||
| .. gh-issue: 135661 | ||
| .. nonce: abc123 | ||
| .. section: Security | ||
|
|
||
| Fix a thing. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| .. cve: CVE-2025-12345 | ||
| .. date: 2026-10-14 | ||
| .. gh-issue: 135661 | ||
| .. nonce: abc123 | ||
| .. section: Security | ||
|
|
||
| Fix a thing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This opens the file a second time. Not a big deal as it's a small file, but perhaps we could read just once and pass the contents?
Actually, I think it would be cleaner to move this parsing into the main parser at
Blurbs.parse()and drop this function and secondopen.