Merge ~pfsmorigo/ubuntu-cve-tracker:pfsmorigo/priority-reason into ubuntu-cve-tracker:master

Proposed by Paulo Flabiano Smorigo
Status: Merged
Merged at revision: 7a65edaede42610c3f147c8d3c57d83b6c641741
Proposed branch: ~pfsmorigo/ubuntu-cve-tracker:pfsmorigo/priority-reason
Merge into: ubuntu-cve-tracker:master
Diff against target: 408 lines (+53/-30)
23 files modified
scripts/active_edit (+4/-1)
scripts/check-syntax (+1/-1)
scripts/cve_lib.py (+22/-5)
scripts/cve_packages (+3/-3)
scripts/oval_lib.py (+3/-3)
scripts/publish-cves-to-website-api.py (+1/-1)
scripts/report-date.py (+2/-2)
scripts/sis-generate-usn (+2/-2)
test/okay/cve-id-N7.json (+1/-1)
test/okay/cve-id-NNNN.json (+1/-1)
test/okay/patches-missing-1.json (+1/-1)
test/okay/patches-missing-2.json (+1/-1)
test/okay/patches-missing-3.json (+1/-1)
test/okay/patches-missing-4.json (+1/-1)
test/okay/priority-critical (+1/-0)
test/okay/priority-critical.json (+1/-1)
test/okay/priority-high (+1/-0)
test/okay/priority-high.json (+1/-1)
test/okay/priority-low (+1/-0)
test/okay/priority-low.json (+1/-1)
test/okay/priority-medium.json (+1/-1)
test/okay/priority-negligible.json (+1/-1)
test/okay/priority-untriaged.json (+1/-1)
Reviewer Review Type Date Requested Status
Alex Murray Approve
Review via email: mp+437974@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Alex Murray (alexmurray) wrote :

A few general questions:

1. Should the name just be Reason instead of Priority-Reason to make it easier?
2. What if instead we extended the syntax to allow the reason to be listed directly underneath the priority, e.g.

Priority: low
  classified as low since it is not a real vulnerability

as I think this is easier to read personally and it keeps the reason with the Priority

3. Or instead it could be a comment after the priority (but this would mean we couldn't easily do long Reason's) e.g.

Priority: low # classified as low since it is not a real vulnerability

4. Like Notes: do we want to capture who added the reason?
5. Do we also need to update all the boilerplates?
6. I think the check for this should be removed from cve_lib.py and instead added to check-syntax as this feels more like a policy check than a low-level format check
7. Can we please have a unit test in test_cve_lib.py?

Revision history for this message
Paulo Flabiano Smorigo (pfsmorigo) wrote :

Thanks for the feedback. About the questions...

1. Leaving just as Reason feels vague but I'm ok to use it instead. This change also works for the package priority so, for instance, Priority-Reason_koffice would be just Reason_koffice.

2 and 3. I'm ok with both alternatives as long as we have a good way to parse it properly. Maybe parentesis like we do for package states: "Priority: low (it is not a real vulnerability)"

4. Not sure. We can always check git for the author. Not sure if it matters for the person browsing the CVE.

5. If we go with 2 and 3 suggestions, only the boilerplates that has a low/high/critical would be modified. Nowadays only one boilerplate has low (thunderbird). Now, if we make it mandatory, we would need to change all CVE that fits the criteria.

6. check-syntax uses a function in cve_lib.py to verify the CVEs. I just added an additional check there for the priority reason.

Revision history for this message
Paulo Flabiano Smorigo (pfsmorigo) wrote :

AlexM: I changed the format to be a comment in parenthesis after the tag. I still using priority-reason for the name but I'm ok about using other term. Also, maybe we can start without enforcing it for now. Otherwise we will need to add a reason for all the CVEs we have that fits the criteria.

Revision history for this message
Camila Camargo de Matos (ccdm94) wrote :

Since the priority reason will need to be short because it will be included in the parenthesis, maybe it is interesting to come with some "default" possible texts to include, so that we can use them as reference. For example, when we update the status of a release to 'not-affected', for example, and the reason behind it not being affected is because the function being patched doesn't exist, or because the code doesn't include some other function which is needed to trigger the vulnerability, we usually put something like 'code not present' for all cases. I don't know if this PR is the right one to possibly include these changes, but it could be useful for some cases that are commonly found during triage. An example would be a 'code not compiled in Ubuntu' for a priority set as 'low'.

Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM!

review: Approve
Revision history for this message
Paulo Flabiano Smorigo (pfsmorigo) wrote :

Hello Alex and other reviewers,

A couple of months ago we had a discussion and I did all the changes at the time. I was waiting for the review but I just realised that I didn't push the new changes to this PR so I did it now. I took the opportunity to change a little bit and merged all commits into one.

This commit will:
 - Change the priority field to a tuple in the format ('priority', 'priority reason');
 - The format for the reason will be a line after the Priority field with a space at the begin:

Priority: high
 classified as high because...

 - It will make check_syntax complains if priority is other than 'medium' and there is no reason for it;
 - The check only complains if the PublishDate is after this month (avoid check in old CVEs);

Revision history for this message
Alex Murray (alexmurray) wrote :

LGTM still - thanks @pfsmorigo

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/scripts/active_edit b/scripts/active_edit
2index 4e2be92..d9068d6 100755
3--- a/scripts/active_edit
4+++ b/scripts/active_edit
5@@ -232,7 +232,10 @@ def create_or_update_cve(cve, packages, priority=None, bug_urls=None, ref_urls=N
6 print('Bugs:', file=fp)
7 for url in (bug_urls if bug_urls else []):
8 print(" %s" % url, file=fp)
9- print('Priority: %s' % (priority if priority else "untriaged"), file=fp)
10+ priority_text = priority if priority else "untriaged"
11+ if priority in cve_lib.PRIORITY_REASON_REQUIRED:
12+ priority_text += "\n XXX-Reason-XXX"
13+ print('Priority: %s' % priority_text, file=fp)
14 print('Discovered-by:', file=fp)
15 print('Assigned-to:', file=fp)
16 print('CVSS:', file=fp)
17diff --git a/scripts/check-syntax b/scripts/check-syntax
18index f3a5128..2bf4202 100755
19--- a/scripts/check-syntax
20+++ b/scripts/check-syntax
21@@ -764,7 +764,7 @@ def check_cve(cve):
22 if (
23 len(supported)
24 and (is_active(cve) or is_embargoed(cve))
25- and ("Priority" not in data or data["Priority"] not in cve_lib.priorities)
26+ and ("Priority" not in data or data["Priority"][0] not in cve_lib.priorities)
27 ):
28 filename = srcmap["Priority"][0] if "Priority" in srcmap else cvepath
29 linenum = srcmap["Priority"][1] if "Priority" in srcmap else 1
30diff --git a/scripts/cve_lib.py b/scripts/cve_lib.py
31index 9b2e44e..d90dbd7 100755
32--- a/scripts/cve_lib.py
33+++ b/scripts/cve_lib.py
34@@ -64,6 +64,8 @@ else:
35 boilerplates_dir = "boilerplates"
36
37 PRODUCT_UBUNTU = "ubuntu"
38+PRIORITY_REASON_REQUIRED = ["low", "high", "critical"]
39+PRIORITY_REASON_DATE_START = "2023-07-11"
40
41 # common to all scripts
42 # these get populated by the contents of subprojects defined below
43@@ -1856,8 +1858,8 @@ def contextual_priority(cveinfo, pkg=None, rel=None):
44 if rel_p in cveinfo:
45 return 2, cveinfo[rel_p]
46 if pkg_p in cveinfo:
47- return 1, cveinfo[pkg_p]
48- return 0, cveinfo.get('Priority', 'untriaged')
49+ return 1, cveinfo[pkg_p][0]
50+ return 0, cveinfo['Priority'][0] if 'Priority' in cveinfo else 'untriaged'
51
52
53 def find_cve(cve):
54@@ -2095,6 +2097,7 @@ def load_cve(cve, strict=False, srcmap=None):
55 raise ValueError("File does not exist: '%s'" % (cve))
56 linenum = 0
57 notes_parser = NotesParser()
58+ priority_reason = {}
59 cvss_entries = []
60 with codecs.open(cve, encoding="utf-8") as inF:
61 lines = inF.readlines()
62@@ -2112,6 +2115,12 @@ def load_cve(cve, strict=False, srcmap=None):
63 code, newmsg = notes_parser.parse_line(cve, line, linenum, code)
64 if code != EXIT_OKAY:
65 msg += newmsg
66+ elif lastfield.startswith('Priority'):
67+ priority_part = lastfield.split('_')[1] if '_' in lastfield else None
68+ if priority_part in priority_reason:
69+ priority_reason[priority_part].append(line.strip())
70+ else:
71+ priority_reason[priority_part] = [line.strip()]
72 elif 'Patches_' in lastfield:
73 try:
74 _, pkg = lastfield.split('_', 1)
75@@ -2186,7 +2195,7 @@ def load_cve(cve, strict=False, srcmap=None):
76 msg += "%s: %d: bad field with 'Priority_': '%s'\n" % (cve, linenum, field)
77 code = EXIT_FAIL
78 continue
79- data.setdefault(field, value)
80+ data.setdefault(field, [value])
81 srcmap.setdefault(field, (cve, linenum))
82 if value not in ['untriaged', 'not-for-us'] + priorities:
83 msg += "%s: %d: unknown Priority '%s'\n" % (cve, linenum, value)
84@@ -2265,7 +2274,7 @@ def load_cve(cve, strict=False, srcmap=None):
85
86 # Fill in defaults for missing fields
87 if 'Priority' not in data:
88- data.setdefault('Priority', 'untriaged')
89+ data.setdefault('Priority', ['untriaged'])
90 srcmap.setdefault('Priority', (cve, 1))
91 # Perform override fields
92 if 'PublicDateAtUSN' in data:
93@@ -2277,6 +2286,14 @@ def load_cve(cve, strict=False, srcmap=None):
94 data['PublicDate'] = data['CRD']
95 srcmap['PublicDate'] = srcmap['CRD']
96
97+ if data["PublicDate"] > PRIORITY_REASON_DATE_START and \
98+ data["Priority"][0] in PRIORITY_REASON_REQUIRED and not priority_reason:
99+ msg += "%s: %d: needs a reason for being '%s'\n" % (cve, linenum, data["Priority"][0])
100+ code = EXIT_FAIL
101+ for item in priority_reason:
102+ field = 'Priority' if not item else 'Priority_' + item
103+ data[field].append(' '.join(priority_reason[item]))
104+
105 # entries need an upstream entry if any entries are from the internal
106 # list of subprojects
107 for pkg in affected:
108@@ -2339,7 +2356,7 @@ def load_table(cves, uems, opt=None, rcves=[], icves=[]):
109 # Allow for Priority overrides
110 priority[cve]['default'] = 'untriaged'
111 try:
112- priority[cve]['default'] = info['Priority']
113+ priority[cve]['default'] = info['Priority'][0]
114 except KeyError:
115 priority[cve]['default'] = 'untriaged'
116
117diff --git a/scripts/cve_packages b/scripts/cve_packages
118index da038c4..c4903af 100755
119--- a/scripts/cve_packages
120+++ b/scripts/cve_packages
121@@ -253,9 +253,9 @@ for cve in sorted(cves):
122 if cveinfo[cve]['CVSS']:
123 p = cveinfo[cve]['CVSS'][0]['baseSeverity'].lower()
124 else:
125- p = priority[cve]['default']
126+ p = priority[cve]['default'][0]
127 else:
128- p = priority[cve]['default']
129+ p = priority[cve]['default'][0]
130
131 if pkg in packages:
132 packages[pkg] += 1
133@@ -263,7 +263,7 @@ for cve in sorted(cves):
134 packages[pkg] = 1
135
136 if pkg in priority[cve]:
137- p = priority[cve][pkg]
138+ p = priority[cve][pkg][0]
139
140 if pkg in priorities[p]:
141 priorities[p][pkg] += 1
142diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
143index ed64318..f8decdd 100644
144--- a/scripts/oval_lib.py
145+++ b/scripts/oval_lib.py
146@@ -1266,7 +1266,7 @@ class OvalGeneratorCVE:
147 'cve_title': escape(header['Candidate']),
148 'description': escape('{0} {1}'.format(header['Description'],
149 header['Ubuntu-Description']).strip() + instruction),
150- 'priority': escape(header['Priority']),
151+ 'priority': escape(header['Priority'][0]),
152 'criteria': '',
153 'references': '',
154 'notes': ''
155@@ -1316,7 +1316,7 @@ class OvalGeneratorCVE:
156 # convert additional data <advisory> metadata elements
157 advisory = []
158 advisory.append('<severity>{0}</severity>'.format(
159- escape(header['Priority'].title())))
160+ escape(header['Priority'][0].title())))
161 advisory.append(
162 '<rights>Copyright (C) {0}Canonical Ltd.</rights>'.format(escape(
163 header['PublicDate'].split('-', 1)[0] + ' '
164@@ -2471,7 +2471,7 @@ class OvalGeneratorUSN():
165 return None
166
167 public_date = cve_object['PublicDate']
168- priority = cve_object['Priority']
169+ priority = cve_object['Priority'][0]
170 references = cve_object['References']
171 # TODO: deal with multiple CVSS?
172 cve_info = {
173diff --git a/scripts/publish-cves-to-website-api.py b/scripts/publish-cves-to-website-api.py
174index aa80880..d6af0e7 100755
175--- a/scripts/publish-cves-to-website-api.py
176+++ b/scripts/publish-cves-to-website-api.py
177@@ -166,7 +166,7 @@ def post_single_cve(cve_filename):
178 for [author, note] in cve_data["Notes"]:
179 notes.append({"author": author, "note": note})
180
181- priority = cve_data["Priority"]
182+ priority = cve_data["Priority"][0]
183
184 if priority == "untriaged":
185 priority = "unknown"
186diff --git a/scripts/report-date.py b/scripts/report-date.py
187index c983072..e350e0c 100755
188--- a/scripts/report-date.py
189+++ b/scripts/report-date.py
190@@ -78,9 +78,9 @@ for priority in ['untriaged'] + cve_lib.priorities:
191 continue
192
193 # Only report if we have a matching priority
194- this_priority = info[cve]['Priority']
195+ this_priority = info[cve]['Priority'][0]
196 if info[cve].has_key('Priority_%s' % (pkg)):
197- this_priority = info[cve]['Priority_%s' % (pkg)]
198+ this_priority = info[cve]['Priority_%s' % (pkg)][0]
199 if this_priority == priority:
200 pkglist.add(pkg)
201
202diff --git a/scripts/sis-generate-usn b/scripts/sis-generate-usn
203index 4a46e18..4535210 100755
204--- a/scripts/sis-generate-usn
205+++ b/scripts/sis-generate-usn
206@@ -198,8 +198,8 @@ def check_cve_priority(cve):
207 print("ERROR: {} does not exist in UCT in either {}".format(cve, state),
208 file=sys.stderr)
209 sys.exit(1)
210- if cve_data['Priority'] in ['untriaged', 'not-for-us']:
211- print("ERROR: {} has Priority {}".format(cve, cve_data['Priority']),
212+ if cve_data['Priority'][0] in ['untriaged', 'not-for-us']:
213+ print("ERROR: {} has Priority {}".format(cve, cve_data['Priority'][0]),
214 file=sys.stderr)
215 sys.exit(1)
216
217diff --git a/test/okay/cve-id-N7.json b/test/okay/cve-id-N7.json
218index 6685f37..afbffa1 100644
219--- a/test/okay/cve-id-N7.json
220+++ b/test/okay/cve-id-N7.json
221@@ -13,7 +13,7 @@
222 "Notes": [],
223 "Mitigation": "",
224 "Bugs": "",
225- "Priority": "negligible",
226+ "Priority": ["negligible"],
227 "Discovered-by": "",
228 "Assigned-to": "",
229 "CVSS": [],
230diff --git a/test/okay/cve-id-NNNN.json b/test/okay/cve-id-NNNN.json
231index 1d19260..0c008ca 100644
232--- a/test/okay/cve-id-NNNN.json
233+++ b/test/okay/cve-id-NNNN.json
234@@ -13,7 +13,7 @@
235 "Notes": [],
236 "Mitigation": "",
237 "Bugs": "",
238- "Priority": "negligible",
239+ "Priority": ["negligible"],
240 "Discovered-by": "",
241 "Assigned-to": "",
242 "CVSS": [],
243diff --git a/test/okay/patches-missing-1.json b/test/okay/patches-missing-1.json
244index f438ff6..c78d347 100644
245--- a/test/okay/patches-missing-1.json
246+++ b/test/okay/patches-missing-1.json
247@@ -11,7 +11,7 @@
248 "Notes": [],
249 "Mitigation": "",
250 "Bugs": "",
251- "Priority": "medium",
252+ "Priority": ["medium"],
253 "Discovered-by": "",
254 "Assigned-to": "",
255 "CVSS": [],
256diff --git a/test/okay/patches-missing-2.json b/test/okay/patches-missing-2.json
257index d057b6e..92fac9d 100644
258--- a/test/okay/patches-missing-2.json
259+++ b/test/okay/patches-missing-2.json
260@@ -11,7 +11,7 @@
261 "Notes": [],
262 "Mitigation": "",
263 "Bugs": "",
264- "Priority": "medium",
265+ "Priority": ["medium"],
266 "Discovered-by": "",
267 "Assigned-to": "",
268 "CVSS": [],
269diff --git a/test/okay/patches-missing-3.json b/test/okay/patches-missing-3.json
270index 950893d..b58408e 100644
271--- a/test/okay/patches-missing-3.json
272+++ b/test/okay/patches-missing-3.json
273@@ -13,7 +13,7 @@
274 "Notes": [],
275 "Mitigation": "",
276 "Bugs": "",
277- "Priority": "medium",
278+ "Priority": ["medium"],
279 "Discovered-by": "",
280 "Assigned-to": "",
281 "CVSS": [],
282diff --git a/test/okay/patches-missing-4.json b/test/okay/patches-missing-4.json
283index 6c03170..5ab7913 100644
284--- a/test/okay/patches-missing-4.json
285+++ b/test/okay/patches-missing-4.json
286@@ -13,7 +13,7 @@
287 "Notes": [],
288 "Mitigation": "",
289 "Bugs": "",
290- "Priority": "medium",
291+ "Priority": ["medium"],
292 "Discovered-by": "",
293 "Assigned-to": "",
294 "CVSS": [],
295diff --git a/test/okay/priority-critical b/test/okay/priority-critical
296index 5d20f02..78a81de 100644
297--- a/test/okay/priority-critical
298+++ b/test/okay/priority-critical
299@@ -11,6 +11,7 @@ Notes:
300 Mitigation:
301 Bugs:
302 Priority: critical
303+ reason for being critial
304 Discovered-by:
305 Assigned-to:
306 CVSS:
307diff --git a/test/okay/priority-critical.json b/test/okay/priority-critical.json
308index 5b99773..89cbce9 100644
309--- a/test/okay/priority-critical.json
310+++ b/test/okay/priority-critical.json
311@@ -13,7 +13,7 @@
312 "Notes": [],
313 "Mitigation": "",
314 "Bugs": "",
315- "Priority": "critical",
316+ "Priority": ["critical", "reason for being critial"],
317 "Discovered-by": "",
318 "Assigned-to": "",
319 "CVSS": [],
320diff --git a/test/okay/priority-high b/test/okay/priority-high
321index f97416a..5ec543f 100644
322--- a/test/okay/priority-high
323+++ b/test/okay/priority-high
324@@ -11,6 +11,7 @@ Notes:
325 Mitigation:
326 Bugs:
327 Priority: high
328+ reason for being high
329 Discovered-by:
330 Assigned-to:
331 CVSS:
332diff --git a/test/okay/priority-high.json b/test/okay/priority-high.json
333index 1c91a1f..f893e73 100644
334--- a/test/okay/priority-high.json
335+++ b/test/okay/priority-high.json
336@@ -13,7 +13,7 @@
337 "Notes": [],
338 "Mitigation": "",
339 "Bugs": "",
340- "Priority": "high",
341+ "Priority": ["high", "reason for being high"],
342 "Discovered-by": "",
343 "Assigned-to": "",
344 "CVSS": [],
345diff --git a/test/okay/priority-low b/test/okay/priority-low
346index 62d21c5..8c5050c 100644
347--- a/test/okay/priority-low
348+++ b/test/okay/priority-low
349@@ -11,6 +11,7 @@ Notes:
350 Mitigation:
351 Bugs:
352 Priority: low
353+ reason for being low
354 Discovered-by:
355 Assigned-to:
356 CVSS:
357diff --git a/test/okay/priority-low.json b/test/okay/priority-low.json
358index 76eb0f6..8eadf86 100644
359--- a/test/okay/priority-low.json
360+++ b/test/okay/priority-low.json
361@@ -13,7 +13,7 @@
362 "Notes": [],
363 "Mitigation": "",
364 "Bugs": "",
365- "Priority": "low",
366+ "Priority": ["low", "reason for being low"],
367 "Discovered-by": "",
368 "Assigned-to": "",
369 "CVSS": [],
370diff --git a/test/okay/priority-medium.json b/test/okay/priority-medium.json
371index acd1505..03aa9f2 100644
372--- a/test/okay/priority-medium.json
373+++ b/test/okay/priority-medium.json
374@@ -13,7 +13,7 @@
375 "Notes": [],
376 "Mitigation": "",
377 "Bugs": "",
378- "Priority": "medium",
379+ "Priority": ["medium"],
380 "Discovered-by": "",
381 "Assigned-to": "",
382 "CVSS": [],
383diff --git a/test/okay/priority-negligible.json b/test/okay/priority-negligible.json
384index 16783ce..5035758 100644
385--- a/test/okay/priority-negligible.json
386+++ b/test/okay/priority-negligible.json
387@@ -13,7 +13,7 @@
388 "Notes": [],
389 "Mitigation": "",
390 "Bugs": "",
391- "Priority": "negligible",
392+ "Priority": ["negligible"],
393 "Discovered-by": "",
394 "Assigned-to": "",
395 "CVSS": [],
396diff --git a/test/okay/priority-untriaged.json b/test/okay/priority-untriaged.json
397index ab2ece0..a596046 100644
398--- a/test/okay/priority-untriaged.json
399+++ b/test/okay/priority-untriaged.json
400@@ -13,7 +13,7 @@
401 "Notes": [],
402 "Mitigation": "",
403 "Bugs": "",
404- "Priority": "untriaged",
405+ "Priority": ["untriaged"],
406 "Discovered-by": "",
407 "Assigned-to": "",
408 "CVSS": [],

Subscribers

People subscribed via source and target branches