Merge ~eslerm/ubuntu-cve-tracker:check-cves-f-strings into ubuntu-cve-tracker:master
- Git
- lp:~eslerm/ubuntu-cve-tracker
- check-cves-f-strings
- Merge into master
Status: | Merged |
---|---|
Merged at revision: | 6f6eb4c1ef0abf924ca1755f68da9bfb3b5aa8cf |
Proposed branch: | ~eslerm/ubuntu-cve-tracker:check-cves-f-strings |
Merge into: | ubuntu-cve-tracker:master |
Diff against target: |
701 lines (+123/-117) 1 file modified
scripts/check-cves (+123/-117) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Steve Beattie | Approve | ||
Marc Deslauriers | Approve | ||
Review via email: mp+462539@code.launchpad.net |
Commit message
check-cves: switch formatting regular strings to f-strings and friends
Description of the change
Converts formatting of regular strings to f-strings.
> F-strings provide a concise, readable way to include the value of Python expressions inside strings.
https:/
f-strings were introduced in 3.6. This means that f-strings work on bionic++.
There are four remaining cases involving regex that I did not want to change and test in this MR.
There are several cases where `print("%s" % foo)` is replaced as `print(foo)`.
And a case where concatenating strings was clearer. e.g., `str_a + str_b`
Note that f-strings cannot contain backslashes, hence cases like `print(" %s" % "\n ".join(info))` are kept.
This is my second time linting check-cves to use f-strings. I reviewed my code several times for errors after my final commit and ran several use cases.
Steve Beattie (sbeattie) wrote : | # |
review approve
On Fri, Mar 15, 2024 at 10:52:17PM -0000, Mark Esler wrote:
> @@ -1344,20 +1351,20 @@ class CVEHandler(
> if dpkg_compare_
> if rel == cve_lib.
> rel = 'devel'
> - fixed_in += ",%s,%s" % (rel, version)
> + fixed_in += f",{rel},{version}"
> break
> elif self.debian[
> len(self.
> # capture that debian believes their version is unaffected
> - not_affected.
> - cmd += ['-p', "%s%s" % (pkg, fixed_in)]
> + not_affected.
Note that the append() call here gets converted from a tuple to two
arguments, which append() won't accept. I added a commit to reinstate
the tuple:
https:/
and have merged your changes with it to master.
Thanks!
--
Steve Beattie
<email address hidden>
Marc Deslauriers (mdeslaur) wrote : | # |
Oh, nice catch, I didn't notice that one.
Mark Esler (eslerm) wrote : | # |
Thank you for the thorough review and merge!
Preview Diff
1 | diff --git a/scripts/check-cves b/scripts/check-cves | |||
2 | index 0ce30ef..c00cd27 100755 | |||
3 | --- a/scripts/check-cves | |||
4 | +++ b/scripts/check-cves | |||
5 | @@ -254,7 +254,7 @@ def import_debian(handler): | |||
6 | 254 | for cve in dsas[dsa]['cves']: | 254 | for cve in dsas[dsa]['cves']: |
7 | 255 | if not cve_lib.CVE_RE.match(cve): | 255 | if not cve_lib.CVE_RE.match(cve): |
8 | 256 | if args.verbose: | 256 | if args.verbose: |
10 | 257 | print("Skipping %s, not well-formed?" % cve, file=sys.stderr) | 257 | print(f"Skipping {cve}, not well-formed?", file=sys.stderr) |
11 | 258 | continue | 258 | continue |
12 | 259 | 259 | ||
13 | 260 | year = int(re.split('-', cve)[1]) | 260 | year = int(re.split('-', cve)[1]) |
14 | @@ -275,27 +275,27 @@ def import_debian(handler): | |||
15 | 275 | cves[cve]['date'] = dsas[dsa]['date'] | 275 | cves[cve]['date'] = dsas[dsa]['date'] |
16 | 276 | 276 | ||
17 | 277 | if args.verbose: | 277 | if args.verbose: |
19 | 278 | print("Processing %s: %s (%s)" % (dsa, dsas[dsa]['desc'], cves[cve]['date']), file=sys.stderr) | 278 | print(f"Processing {dsa}: {dsas[dsa]['desc']} ({cves[cve]['date']})", file=sys.stderr) |
20 | 279 | 279 | ||
21 | 280 | # Now pull in CVEs from the data/CVE/list | 280 | # Now pull in CVEs from the data/CVE/list |
22 | 281 | for cve in handler.debian: | 281 | for cve in handler.debian: |
23 | 282 | if args.verbose: | 282 | if args.verbose: |
25 | 283 | print("[--- Processing %s ---]" % cve, file=sys.stderr) | 283 | print(f"[--- Processing {cve} ---]", file=sys.stderr) |
26 | 284 | 284 | ||
27 | 285 | if cve in cves: | 285 | if cve in cves: |
28 | 286 | if args.verbose: | 286 | if args.verbose: |
30 | 287 | print("Skipping %s, already found in DSA" % cve, file=sys.stderr) | 287 | print(f"Skipping {cve}, already found in DSA", file=sys.stderr) |
31 | 288 | continue | 288 | continue |
32 | 289 | 289 | ||
33 | 290 | if not cve_lib.CVE_RE.match(cve): | 290 | if not cve_lib.CVE_RE.match(cve): |
34 | 291 | if args.verbose: | 291 | if args.verbose: |
36 | 292 | print("Skipping %s, not well-formed?" % cve, file=sys.stderr) | 292 | print(f"Skipping {cve}, not well-formed?", file=sys.stderr) |
37 | 293 | continue | 293 | continue |
38 | 294 | 294 | ||
39 | 295 | year = int(re.split('-', cve)[1]) | 295 | year = int(re.split('-', cve)[1]) |
40 | 296 | if year < cve_limit: | 296 | if year < cve_limit: |
41 | 297 | if args.verbose: | 297 | if args.verbose: |
43 | 298 | print("Skipping %s, year %d predates %d" % (cve, year, cve_limit), file=sys.stderr) | 298 | print(f"Skipping {cve}, year {year} predates {cve_limit}", file=sys.stderr) |
44 | 299 | continue | 299 | continue |
45 | 300 | 300 | ||
46 | 301 | # If we already know about the CVE, skip it unless is mistriaged | 301 | # If we already know about the CVE, skip it unless is mistriaged |
47 | @@ -305,7 +305,7 @@ def import_debian(handler): | |||
48 | 305 | handler.debian[cve]['desc'] = mistriaged_hint + handler.debian[cve]['desc'] | 305 | handler.debian[cve]['desc'] = mistriaged_hint + handler.debian[cve]['desc'] |
49 | 306 | else: | 306 | else: |
50 | 307 | if args.verbose: | 307 | if args.verbose: |
52 | 308 | print("Skipping %s, already known" % cve, file=sys.stderr) | 308 | print(f"Skipping {cve}, already known", file=sys.stderr) |
53 | 309 | continue | 309 | continue |
54 | 310 | 310 | ||
55 | 311 | if handler.debian[cve]['desc'] or handler.debian[cve]['state'] == 'FOUND': | 311 | if handler.debian[cve]['desc'] or handler.debian[cve]['state'] == 'FOUND': |
56 | @@ -315,13 +315,13 @@ def import_debian(handler): | |||
57 | 315 | cves[cve]['subject'] = '[Unknown description]' | 315 | cves[cve]['subject'] = '[Unknown description]' |
58 | 316 | 316 | ||
59 | 317 | # just make something up. It'll get adjusted whenever mitre adds it | 317 | # just make something up. It'll get adjusted whenever mitre adds it |
61 | 318 | date = "%s-12-31" % year | 318 | date = f"{year}-12-31" |
62 | 319 | if year >= today.year: | 319 | if year >= today.year: |
64 | 320 | date = "%s-%s-%s" % (today.year, today.month, today.day) | 320 | date = f"{today.year}-{today.month}-{today.day}" |
65 | 321 | cves[cve]['date'] = datetime.strptime(date, "%Y-%m-%d") | 321 | cves[cve]['date'] = datetime.strptime(date, "%Y-%m-%d") |
66 | 322 | 322 | ||
67 | 323 | if args.verbose: | 323 | if args.verbose: |
69 | 324 | print("Processing %s: %s (%s)" % (cve, handler.debian[cve]['desc'], cves[cve]['date']), file=sys.stderr) | 324 | print(f"Processing {cve}: {handler.debian[cve]['desc']} ({cves[cve]['date']})", file=sys.stderr) |
70 | 325 | 325 | ||
71 | 326 | nvd = convert_to_nvd(cves, lambda cve: cves[cve]['subject']) | 326 | nvd = convert_to_nvd(cves, lambda cve: cves[cve]['subject']) |
72 | 327 | tmp = tempfile.NamedTemporaryFile(mode='w', prefix='debian-import_', suffix='.json', delete=False) | 327 | tmp = tempfile.NamedTemporaryFile(mode='w', prefix='debian-import_', suffix='.json', delete=False) |
73 | @@ -397,12 +397,12 @@ def read_rhel8oval_file(f): | |||
74 | 397 | file for processing. | 397 | file for processing. |
75 | 398 | ''' | 398 | ''' |
76 | 399 | if not os.path.isfile(f): | 399 | if not os.path.isfile(f): |
78 | 400 | print("'%s' not a file" % f, file=sys.stderr) | 400 | print(f"'{f}' not a file", file=sys.stderr) |
79 | 401 | sys.exit(1) | 401 | sys.exit(1) |
80 | 402 | 402 | ||
81 | 403 | name = os.path.abspath(f + ".json") | 403 | name = os.path.abspath(f + ".json") |
82 | 404 | if os.path.exists(name): | 404 | if os.path.exists(name): |
84 | 405 | print("'%s' already exists" % name, file=sys.stderr) | 405 | print(f"'{name}' already exists", file=sys.stderr) |
85 | 406 | sys.exit(1) | 406 | sys.exit(1) |
86 | 407 | 407 | ||
87 | 408 | parser = xml.sax.make_parser() | 408 | parser = xml.sax.make_parser() |
88 | @@ -425,12 +425,12 @@ def read_locate_cves_output(f): | |||
89 | 425 | file for processing. | 425 | file for processing. |
90 | 426 | ''' | 426 | ''' |
91 | 427 | if not os.path.isfile(f): | 427 | if not os.path.isfile(f): |
93 | 428 | print("'%s' not a file" % f, file=sys.stderr) | 428 | print(f"'{f}' not a file", file=sys.stderr) |
94 | 429 | sys.exit(1) | 429 | sys.exit(1) |
95 | 430 | 430 | ||
96 | 431 | name = os.path.abspath(f + ".json") | 431 | name = os.path.abspath(f + ".json") |
97 | 432 | if os.path.exists(name): | 432 | if os.path.exists(name): |
99 | 433 | print("'%s' already exists" % name, file=sys.stderr) | 433 | print(f"'{name}' already exists", file=sys.stderr) |
100 | 434 | sys.exit(1) | 434 | sys.exit(1) |
101 | 435 | 435 | ||
102 | 436 | with open(f) as _f: | 436 | with open(f) as _f: |
103 | @@ -449,15 +449,15 @@ def read_locate_cves_output(f): | |||
104 | 449 | if line.startswith("Couldn't find CVE"): | 449 | if line.startswith("Couldn't find CVE"): |
105 | 450 | cve = line.split()[2] | 450 | cve = line.split()[2] |
106 | 451 | if not cve_lib.CVE_RE.match(cve): | 451 | if not cve_lib.CVE_RE.match(cve): |
108 | 452 | print("Skipping malformed CVE: '%s' from '%s'" % (cve, f), file=sys.stderr) | 452 | print(f"Skipping malformed CVE: '{cve}' from '{f}'", file=sys.stderr) |
109 | 453 | cve = None | 453 | cve = None |
110 | 454 | elif cve in cves: | 454 | elif cve in cves: |
111 | 455 | if args.verbose: | 455 | if args.verbose: |
113 | 456 | print("Skipping duplicate '%s' from '%s'" % (cve, f), file=sys.stderr) | 456 | print(f"Skipping duplicate '{cve}' from '{f}'", file=sys.stderr) |
114 | 457 | cve = None | 457 | cve = None |
115 | 458 | else: | 458 | else: |
116 | 459 | if args.verbose: | 459 | if args.verbose: |
118 | 460 | print("Adding '%s'" % cve, file=sys.stderr) | 460 | print(f"Adding '{cve}'", file=sys.stderr) |
119 | 461 | cves[cve] = dict() | 461 | cves[cve] = dict() |
120 | 462 | continue | 462 | continue |
121 | 463 | 463 | ||
122 | @@ -469,7 +469,7 @@ def read_locate_cves_output(f): | |||
123 | 469 | date = " ".join(line.split(": ")[1].strip().split()[0:5]) | 469 | date = " ".join(line.split(": ")[1].strip().split()[0:5]) |
124 | 470 | cves[cve]['date'] = datetime.strptime(date, "%a, %d %b %Y %H:%M:%S") | 470 | cves[cve]['date'] = datetime.strptime(date, "%a, %d %b %Y %H:%M:%S") |
125 | 471 | except Exception: | 471 | except Exception: |
127 | 472 | print("Could not process date '%s', skipping %s from '%s'" % (line, cve, f), file=sys.stderr) | 472 | print(f"Could not process date '{line}', skipping {cve} from '{f}'", file=sys.stderr) |
128 | 473 | del cves[cve] | 473 | del cves[cve] |
129 | 474 | cve = None | 474 | cve = None |
130 | 475 | continue | 475 | continue |
131 | @@ -491,11 +491,10 @@ def read_locate_cves_output(f): | |||
132 | 491 | # NOTE: while we can determine the url for the year/month/day, we | 491 | # NOTE: while we can determine the url for the year/month/day, we |
133 | 492 | # cannot determine the specific message on that day. This gets us | 492 | # cannot determine the specific message on that day. This gets us |
134 | 493 | # close though, so use it. | 493 | # close though, so use it. |
136 | 494 | url = "http://www.openwall.com/lists/oss-security/%s" % (cves[cve]['date'].strftime("%Y/%m/%d")) | 494 | url = "http://www.openwall.com/lists/oss-security/" + cves[cve]['date'].strftime('%Y/%m/%d') |
137 | 495 | cves[cve].setdefault('refs', [] + [url]) | 495 | cves[cve].setdefault('refs', [] + [url]) |
138 | 496 | 496 | ||
141 | 497 | nvd = convert_to_nvd(cves, lambda c: '''ML-Date: %s, ML-Subject: %s''' % | 497 | nvd = convert_to_nvd(cves, lambda c: f'''ML-Date: {cves[c]['date']}, ML-Subject: {escape(cves[c]['subject'])}''') |
140 | 498 | (cves[c]['date'], escape(cves[c]['subject']))) | ||
142 | 499 | 498 | ||
143 | 500 | tmp = tempfile.NamedTemporaryFile(mode='w', prefix='locate-cves-import_', suffix='.json', delete=False) | 499 | tmp = tempfile.NamedTemporaryFile(mode='w', prefix='locate-cves-import_', suffix='.json', delete=False) |
144 | 501 | tmp.file.write(json.dumps(nvd)) | 500 | tmp.file.write(json.dumps(nvd)) |
145 | @@ -510,7 +509,7 @@ def read_mbox_file(f): | |||
146 | 510 | And process through read_locate_cves_output() | 509 | And process through read_locate_cves_output() |
147 | 511 | ''' | 510 | ''' |
148 | 512 | if not os.path.isfile(f) and not os.path.isdir(f): | 511 | if not os.path.isfile(f) and not os.path.isdir(f): |
150 | 513 | print("'%s' not a file" % f, file=sys.stderr) | 512 | print(f"'{f}' not a file", file=sys.stderr) |
151 | 514 | sys.exit(1) | 513 | sys.exit(1) |
152 | 515 | 514 | ||
153 | 516 | child = subprocess.Popen(['./scripts/locate_cves.py', f], stdout=subprocess.PIPE, universal_newlines=True) | 515 | child = subprocess.Popen(['./scripts/locate_cves.py', f], stdout=subprocess.PIPE, universal_newlines=True) |
154 | @@ -602,17 +601,23 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
155 | 602 | timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) | 601 | timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) |
156 | 603 | 602 | ||
157 | 604 | # Append to timestamp file list | 603 | # Append to timestamp file list |
161 | 605 | with open('%s/check-cves.log' % (destdir), 'a') as f: | 604 | with open(f'{destdir}/check-cves.log', 'a') as f: |
162 | 606 | f.write('%s UTC - %s added, %s ignored, %s skipped, %s total - files: %s\n' % | 605 | f.write( |
163 | 607 | (timestamp, self.num_added, self.num_ignored, self.num_skipped, self.num_added + self.num_ignored, [os.path.basename(x) for x in args.uris])) | 606 | f"{timestamp} UTC - " |
164 | 607 | f"{self.num_added} added, " | ||
165 | 608 | f"{self.num_ignored} ignored, " | ||
166 | 609 | f"{self.num_skipped} skipped, " | ||
167 | 610 | f"{self.num_added + self.num_ignored} total - " | ||
168 | 611 | f"files: {[os.path.basename(x) for x in args.uris]}\n" | ||
169 | 612 | ) | ||
170 | 608 | 613 | ||
171 | 609 | def printReport(self): | 614 | def printReport(self): |
172 | 610 | print('\n============================ Triage summary =============================') | 615 | print('\n============================ Triage summary =============================') |
176 | 611 | print("\n %4d CVEs added" % self.num_added) | 616 | print(f"\n {self.num_added: 4d} CVEs added") |
177 | 612 | print(" %4d CVEs ignored" % self.num_ignored) | 617 | print(f" {self.num_ignored: 4d} CVEs ignored") |
178 | 613 | print(" %4d CVEs skipped" % self.num_skipped) | 618 | print(f" {self.num_skipped: 4d} CVEs skipped") |
179 | 614 | print("---------------------------") | 619 | print("---------------------------") |
181 | 615 | print("%5d total CVEs triaged" % (self.num_added + self.num_ignored)) | 620 | print(f"{self.num_added + self.num_ignored: 5d} total CVEs triaged") |
182 | 616 | updates_detected, updates_details = self.detect_updates_to_external_repositories() | 621 | updates_detected, updates_details = self.detect_updates_to_external_repositories() |
183 | 617 | if updates_detected: | 622 | if updates_detected: |
184 | 618 | print('\n====================== External updates detected ========================') | 623 | print('\n====================== External updates detected ========================') |
185 | @@ -636,7 +641,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
186 | 636 | if process.returncode == 0 and process.stdout: | 641 | if process.returncode == 0 and process.stdout: |
187 | 637 | if process.stdout: | 642 | if process.stdout: |
188 | 638 | updates_detected = True | 643 | updates_detected = True |
190 | 639 | updates_details += "\n %s \n %s" % (repository_dir, process.stdout) | 644 | updates_details += f"\n {repository_dir} \n {process.stdout}" |
191 | 640 | except subprocess.CalledProcessError as exception: | 645 | except subprocess.CalledProcessError as exception: |
192 | 641 | print(exception) | 646 | print(exception) |
193 | 642 | updates_detected = False | 647 | updates_detected = False |
194 | @@ -657,11 +662,11 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
195 | 657 | "data_version": "4.0"} | 662 | "data_version": "4.0"} |
196 | 658 | for key in list(template_cve.keys()): | 663 | for key in list(template_cve.keys()): |
197 | 659 | if key not in cve or cve[key] != template_cve[key]: | 664 | if key not in cve or cve[key] != template_cve[key]: |
199 | 660 | raise KeyError("NVD JSON in '%s' seems invalid" % fp.name) | 665 | raise KeyError(f"NVD JSON in '{fp.name}' seems invalid") |
200 | 661 | 666 | ||
201 | 662 | metadata = cve["CVE_data_meta"] | 667 | metadata = cve["CVE_data_meta"] |
202 | 663 | if not re.match(r'^CVE-\d{4}-\d{4,}$', metadata["ID"]): | 668 | if not re.match(r'^CVE-\d{4}-\d{4,}$', metadata["ID"]): |
204 | 664 | print("Ignoring invalid CVE with ID '%s'" % metadata["ID"]) | 669 | print(f"Ignoring invalid CVE with ID '{metadata['ID']}'") |
205 | 665 | return | 670 | return |
206 | 666 | self.curr_cve = metadata["ID"] | 671 | self.curr_cve = metadata["ID"] |
207 | 667 | 672 | ||
208 | @@ -693,7 +698,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
209 | 693 | # check for expected fields | 698 | # check for expected fields |
210 | 694 | for key in list(template_nvd.keys()): | 699 | for key in list(template_nvd.keys()): |
211 | 695 | if key not in record or record[key] != template_nvd[key]: | 700 | if key not in record or record[key] != template_nvd[key]: |
213 | 696 | raise KeyError("NVD JSON in '%s' seems invalid - missing key '%s'" % (fp.name, key)) | 701 | raise KeyError(f"NVD JSON in '{fp.name}' seems invalid - missing key '{key}'") |
214 | 697 | for item in record["CVE_Items"]: | 702 | for item in record["CVE_Items"]: |
215 | 698 | self.curr_cvss = [] | 703 | self.curr_cvss = [] |
216 | 699 | self.curr_refs = [] | 704 | self.curr_refs = [] |
217 | @@ -787,7 +792,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
218 | 787 | return | 792 | return |
219 | 788 | 793 | ||
220 | 789 | if self.curr_cve in self.cve_seen: | 794 | if self.curr_cve in self.cve_seen: |
222 | 790 | print("Skipping repeat: %s" % (self.curr_cve), file=sys.stderr) | 795 | print(f"Skipping repeat: {self.curr_cve}", file=sys.stderr) |
223 | 791 | return | 796 | return |
224 | 792 | self.cve_seen.add(self.curr_cve) | 797 | self.cve_seen.add(self.curr_cve) |
225 | 793 | 798 | ||
226 | @@ -802,18 +807,20 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
227 | 802 | return self.cve_list | 807 | return self.cve_list |
228 | 803 | 808 | ||
229 | 804 | def display_command_file_usage(self, f, line_prefix=''): | 809 | def display_command_file_usage(self, f, line_prefix=''): |
242 | 805 | f.write('%sThe following commands can be used in this file:\n' % (line_prefix)) | 810 | # fmt: off |
243 | 806 | f.write('%s\n' % (line_prefix)) | 811 | f.write(f'{line_prefix}The following commands can be used in this file:\n') |
244 | 807 | f.write('%s* Add a new CVE to the tracker:\n' % (line_prefix)) | 812 | f.write(f'{line_prefix}\n') |
245 | 808 | f.write('%s <CVE> add <PRIORITY> <PACKAGE> [PACKAGE] ...\n' % (line_prefix)) | 813 | f.write(f'{line_prefix}* Add a new CVE to the tracker:\n') |
246 | 809 | f.write('%s* Add a new CVE to the tracker and open it in your editor:\n' % (line_prefix)) | 814 | f.write(f'{line_prefix} <CVE> add <PRIORITY> <PACKAGE> [PACKAGE] ...\n') |
247 | 810 | f.write('%s <CVE> edit <PRIORITY> <PACKAGE> [PACKAGE] ...\n' % (line_prefix)) | 815 | f.write(f'{line_prefix}* Add a new CVE to the tracker and open it in your editor:\n') |
248 | 811 | f.write('%s* Unembargo a CVE that is now public:\n' % (line_prefix)) | 816 | f.write(f'{line_prefix} <CVE> edit <PRIORITY> <PACKAGE> [PACKAGE] ...\n') |
249 | 812 | f.write('%s <CVE> unembargo>\n' % (line_prefix)) | 817 | f.write(f'{line_prefix}* Unembargo a CVE that is now public:\n') |
250 | 813 | f.write('%s* Permanently ignore a CVE:\n' % (line_prefix)) | 818 | f.write(f'{line_prefix} <CVE> unembargo>\n') |
251 | 814 | f.write('%s <CVE> ignore <REASON>\n' % (line_prefix)) | 819 | f.write(f'{line_prefix}* Permanently ignore a CVE:\n') |
252 | 815 | f.write('%s* Temporarily skip over a CVE:\n' % (line_prefix)) | 820 | f.write(f'{line_prefix} <CVE> ignore <REASON>\n') |
253 | 816 | f.write('%s <CVE> skip\n\n' % (line_prefix)) | 821 | f.write(f'{line_prefix}* Temporarily skip over a CVE:\n') |
254 | 822 | f.write(f'{line_prefix} <CVE> skip\n\n') | ||
255 | 823 | # fmt: on | ||
256 | 817 | f.flush() | 824 | f.flush() |
257 | 818 | 825 | ||
258 | 819 | def find_hint_in_external_subprojects(self, software_hints_from_cve_description): | 826 | def find_hint_in_external_subprojects(self, software_hints_from_cve_description): |
259 | @@ -861,24 +868,24 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
260 | 861 | print('=================================end details==================================') | 868 | print('=================================end details==================================') |
261 | 862 | # Display CVE information | 869 | # Display CVE information |
262 | 863 | if self.cve_data[cve]['public']: | 870 | if self.cve_data[cve]['public']: |
264 | 864 | print(' Published: %s' % (self.cve_data[cve]['public'])) | 871 | print(f" Published: {self.cve_data[cve]['public']}") |
265 | 865 | for ref in self.cve_data[cve]['refs']: | 872 | for ref in self.cve_data[cve]['refs']: |
267 | 866 | print(' %s: %s' % (ref[0], ref[1]), end='') | 873 | print(f' {ref[0]}: {ref[1]}', end='') |
268 | 867 | # Do not repeat URL if it matches the contents of the reference | 874 | # Do not repeat URL if it matches the contents of the reference |
269 | 868 | if ref[2] and ref[1].strip() != ref[2].strip(): | 875 | if ref[2] and ref[1].strip() != ref[2].strip(): |
271 | 869 | print(' %s' % (ref[2]), end='') | 876 | print(f' {ref[2]}', end='') |
272 | 870 | print() | 877 | print() |
273 | 871 | if wrap_desc: | 878 | if wrap_desc: |
275 | 872 | print('%s' % _wrap_desc(self.cve_data[cve]['desc'])) | 879 | print(_wrap_desc(self.cve_data[cve]['desc'])) |
276 | 873 | else: | 880 | else: |
277 | 874 | print('\n======================== CVE details ==========================') | 881 | print('\n======================== CVE details ==========================') |
280 | 875 | print(' %s' % cve) | 882 | print(f' {cve}') |
281 | 876 | print(' %s' % (self.cve_data[cve]['desc'])) | 883 | print(f" {self.cve_data[cve]['desc']}") |
282 | 877 | for cvss in self.cve_data[cve]['cvss']: | 884 | for cvss in self.cve_data[cve]['cvss']: |
284 | 878 | print(' CVSS (%s): %s [%.1f]' % (cvss['source'], cvss['vector'], cvss['baseScore'])) | 885 | print(f" CVSS ({cvss['source']}): {cvss['vector']} [{cvss['baseScore']: .1f}]") |
285 | 879 | if self.debian and cve in self.debian: | 886 | if self.debian and cve in self.debian: |
286 | 880 | print('\n======================= Debian details ========================') | 887 | print('\n======================= Debian details ========================') |
288 | 881 | print(' Debian CVE Tracker: %s' % (self.debian[cve]['state'])) | 888 | print(f" Debian CVE Tracker: {self.debian[cve]['state']}") |
289 | 882 | if len(self.debian[cve]['note']): | 889 | if len(self.debian[cve]['note']): |
290 | 883 | print("\t" + "\n\t".join(self.debian[cve]['note'])) | 890 | print("\t" + "\n\t".join(self.debian[cve]['note'])) |
291 | 884 | for pkg in self.debian[cve]['pkgs']: | 891 | for pkg in self.debian[cve]['pkgs']: |
292 | @@ -889,23 +896,23 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
293 | 889 | info.append(self.debian[cve]['pkgs'][pkg]['bug']) | 896 | info.append(self.debian[cve]['pkgs'][pkg]['bug']) |
294 | 890 | if self.debian[cve]['pkgs'][pkg]['note']: | 897 | if self.debian[cve]['pkgs'][pkg]['note']: |
295 | 891 | info.append(self.debian[cve]['pkgs'][pkg]['note']) | 898 | info.append(self.debian[cve]['pkgs'][pkg]['note']) |
297 | 892 | print(" Debian: %s: %s (%s)" % (pkg, self.debian[cve]['pkgs'][pkg]['state'], "; ".join(info))) | 899 | print(f" Debian: {pkg}: {self.debian[cve]['pkgs'][pkg]['state']} ({'; '.join(info)})") |
298 | 893 | # Display version and component details for Ubuntu's pkg | 900 | # Display version and component details for Ubuntu's pkg |
299 | 894 | answer = source_map.madison(source, pkg) | 901 | answer = source_map.madison(source, pkg) |
300 | 895 | for name in sorted(answer.keys()): | 902 | for name in sorted(answer.keys()): |
301 | 896 | for pkg in sorted(answer[name].keys()): | 903 | for pkg in sorted(answer[name].keys()): |
303 | 897 | print(' Ubuntu: %s | %s | %s' % (pkg, answer[name][pkg], name)) | 904 | print(f' Ubuntu: {pkg} | {answer[name][pkg]} | {name}') |
304 | 898 | # no debian info, display possible commented ignore command when | 905 | # no debian info, display possible commented ignore command when |
305 | 899 | # using command file (i.e. wrap_desc is true) | 906 | # using command file (i.e. wrap_desc is true) |
306 | 900 | if (self.debian[cve]['state'] == 'RESERVED' or self.debian[cve]['state'] == None) and wrap_desc: | 907 | if (self.debian[cve]['state'] == 'RESERVED' or self.debian[cve]['state'] == None) and wrap_desc: |
307 | 901 | proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) | 908 | proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) |
309 | 902 | print('%s ignore "%s"' % (cve, proposed_ignore)) | 909 | print(f'{cve} ignore "{proposed_ignore}"') |
310 | 903 | # debian rejected, so offer to reject by ignoring when using command file (i.e. wrap_desc is true) | 910 | # debian rejected, so offer to reject by ignoring when using command file (i.e. wrap_desc is true) |
311 | 904 | if (self.debian[cve]['state'] == 'REJECTED' and wrap_desc): | 911 | if (self.debian[cve]['state'] == 'REJECTED' and wrap_desc): |
313 | 905 | print('%s ignore "%s"' % (cve, "REJECTED")) | 912 | print(f'{cve} ignore "REJECTED"') |
314 | 906 | else: | 913 | else: |
315 | 907 | proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) | 914 | proposed_ignore = self.ignore_suggestion.get_ignore_suggestion(self.cve_data[cve]['desc']) |
317 | 908 | print('%s ignore %s' % (cve, proposed_ignore)) | 915 | print(f'{cve} ignore {proposed_ignore}') |
318 | 909 | 916 | ||
319 | 910 | software_hints_from_cve_desc = self.get_software_hints_from_cve_description(self.cve_data[cve]["desc"]) | 917 | software_hints_from_cve_desc = self.get_software_hints_from_cve_description(self.cve_data[cve]["desc"]) |
320 | 911 | if software_hints_from_cve_desc: | 918 | if software_hints_from_cve_desc: |
321 | @@ -953,7 +960,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
322 | 953 | if self.debian[cve]['pkgs'][pkg]['state'] == '<itp>': | 960 | if self.debian[cve]['pkgs'][pkg]['state'] == '<itp>': |
323 | 954 | # software has not been admitted into debian | 961 | # software has not been admitted into debian |
324 | 955 | action = 'ignore' | 962 | action = 'ignore' |
326 | 956 | reason = '%s: <itp> (dbug %s)' % (pkg, self.debian[cve]['pkgs'][pkg]['bug']) | 963 | reason = f"{pkg}: <itp> (dbug {self.debian[cve]['pkgs'][pkg]['bug']})" |
327 | 957 | if self.debian[cve]['state'] == 'REJECTED': | 964 | if self.debian[cve]['state'] == 'REJECTED': |
328 | 958 | action = 'ignore' | 965 | action = 'ignore' |
329 | 959 | reason = 'REJECTED' | 966 | reason = 'REJECTED' |
330 | @@ -1003,7 +1010,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
331 | 1003 | def human_process_cve(self, cve, action='skip', reason='', package=''): | 1010 | def human_process_cve(self, cve, action='skip', reason='', package=''): |
332 | 1004 | info = '' | 1011 | info = '' |
333 | 1005 | while info == "" or not info[0] in ['i', 'a', 's', 'q', 'r']: | 1012 | while info == "" or not info[0] in ['i', 'a', 's', 'q', 'r']: |
335 | 1006 | prompt_user('\nA]dd (or R]epeat), I]gnore forever, S]kip for now, or Q]uit? [%s] ' % (action)) | 1013 | prompt_user(f'\nA]dd (or R]epeat), I]gnore forever, S]kip for now, or Q]uit? [{action}] ') |
336 | 1007 | info = sys.stdin.readline().strip().lower() | 1014 | info = sys.stdin.readline().strip().lower() |
337 | 1008 | if info == "": | 1015 | if info == "": |
338 | 1009 | info = action | 1016 | info = action |
339 | @@ -1023,7 +1030,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
340 | 1023 | if package == "": | 1030 | if package == "": |
341 | 1024 | package = self.saved_package | 1031 | package = self.saved_package |
342 | 1025 | if package != "": | 1032 | if package != "": |
344 | 1026 | prompt_user('[%s] ' % (package)) | 1033 | prompt_user(f'[{package}] ') |
345 | 1027 | info = sys.stdin.readline().strip() | 1034 | info = sys.stdin.readline().strip() |
346 | 1028 | if info == '': | 1035 | if info == '': |
347 | 1029 | info = package | 1036 | info = package |
348 | @@ -1037,19 +1044,19 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
349 | 1037 | self.saved_cve = cve | 1044 | self.saved_cve = cve |
350 | 1038 | 1045 | ||
351 | 1039 | print('\n===================== Dependant packages ======================') | 1046 | print('\n===================== Dependant packages ======================') |
353 | 1040 | print(' Detecting packages built using: %s...' % info, end='') | 1047 | print(f' Detecting packages built using: {info}...', end='') |
354 | 1041 | sys.stdout.flush() | 1048 | sys.stdout.flush() |
355 | 1042 | built_using = "" | 1049 | built_using = "" |
356 | 1043 | try: | 1050 | try: |
357 | 1044 | built_using = get_built_using(info) | 1051 | built_using = get_built_using(info) |
358 | 1045 | except Exception as e: | 1052 | except Exception as e: |
360 | 1046 | print("ERROR: %s" % e, file=sys.stderr) | 1053 | print(f"ERROR: {e}", file=sys.stderr) |
361 | 1047 | pass # for now just show the error but don't break triage | 1054 | pass # for now just show the error but don't break triage |
362 | 1048 | 1055 | ||
363 | 1049 | if built_using != "": | 1056 | if built_using != "": |
364 | 1050 | print("found:\n") | 1057 | print("found:\n") |
367 | 1051 | print("%s" % source_map.get_built_using_header()) | 1058 | print(source_map.get_built_using_header()) |
368 | 1052 | print("%s" % built_using) | 1059 | print(built_using) |
369 | 1053 | print("IMPORTANT: the above packages are candidates for rebuilds when fixes are applied to:") | 1060 | print("IMPORTANT: the above packages are candidates for rebuilds when fixes are applied to:") |
370 | 1054 | print(" %s" % "\n ".join(info)) | 1061 | print(" %s" % "\n ".join(info)) |
371 | 1055 | else: | 1062 | else: |
372 | @@ -1071,7 +1078,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
373 | 1071 | prompts.append(choice) | 1078 | prompts.append(choice) |
374 | 1072 | 1079 | ||
375 | 1073 | for i in range(0, len(prompts)): | 1080 | for i in range(0, len(prompts)): |
377 | 1074 | print(' %s) %s' % (chr(97 + i), prompts[i])) | 1081 | print(f" {chr(97 + i)}) {prompts[i]}") |
378 | 1075 | prompt_user(' > ') | 1082 | prompt_user(' > ') |
379 | 1076 | 1083 | ||
380 | 1077 | info = sys.stdin.readline().strip() | 1084 | info = sys.stdin.readline().strip() |
381 | @@ -1113,13 +1120,13 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
382 | 1113 | try: | 1120 | try: |
383 | 1114 | (cve, action) = (args[0].upper(), args[1].lower()) | 1121 | (cve, action) = (args[0].upper(), args[1].lower()) |
384 | 1115 | except IndexError: | 1122 | except IndexError: |
386 | 1116 | raise ValueError('Invalid formatting on line %d:\n%s' % (line_num, orig_line)) | 1123 | raise ValueError(f'Invalid formatting on line {line_num}:\n{orig_line}') |
387 | 1117 | 1124 | ||
388 | 1118 | if not cve.startswith('CVE-'): | 1125 | if not cve.startswith('CVE-'): |
389 | 1119 | # The first arg should look like a CVE ID | 1126 | # The first arg should look like a CVE ID |
391 | 1120 | raise ValueError('Invalid CVE ID formatting (%s) on line %d:\n%s' % (cve, line_num, orig_line)) | 1127 | raise ValueError(f'Invalid CVE ID formatting ({cve}) on line {line_num}:\n{orig_line}') |
392 | 1121 | elif cve in cves: | 1128 | elif cve in cves: |
394 | 1122 | raise ValueError('Performing multiple operations on the same CVE (%s) is not supported (line %d):\n%s' % (cve, line_num, orig_line)) | 1129 | raise ValueError(f'Performing multiple operations on the same CVE ({cve}) is not supported (line {line_num}):\n{orig_line}') |
395 | 1123 | cves.append(cve) | 1130 | cves.append(cve) |
396 | 1124 | 1131 | ||
397 | 1125 | if action == 'add' or action == 'edit': | 1132 | if action == 'add' or action == 'edit': |
398 | @@ -1130,13 +1137,13 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
399 | 1130 | priority = args[0].lower() | 1137 | priority = args[0].lower() |
400 | 1131 | packages = args[1:] | 1138 | packages = args[1:] |
401 | 1132 | except IndexError: | 1139 | except IndexError: |
403 | 1133 | raise ValueError('Invalid add command on line %d:\n%s' % (line_num, orig_line)) | 1140 | raise ValueError(f'Invalid add command on line {line_num}:\n{orig_line}') |
404 | 1134 | 1141 | ||
405 | 1135 | if not priority in cve_lib.priorities and not priority == 'untriaged': | 1142 | if not priority in cve_lib.priorities and not priority == 'untriaged': |
407 | 1136 | raise ValueError('Invalid priority on line %d:\n%s' % (line_num, orig_line)) | 1143 | raise ValueError(f'Invalid priority on line {line_num}:\n{orig_line}') |
408 | 1137 | 1144 | ||
411 | 1138 | if os.path.exists('%s/active/%s' % (destdir, cve)): | 1145 | if os.path.exists(f'{destdir}/active/{cve}'): |
412 | 1139 | raise ValueError('Updating an existing CVE is not supported (line %d):\n%s' % (line_num, orig_line)) | 1146 | raise ValueError(f'Updating an existing CVE is not supported (line {line_num}):\n{orig_line}') |
413 | 1140 | 1147 | ||
414 | 1141 | if preprocess: | 1148 | if preprocess: |
415 | 1142 | continue | 1149 | continue |
416 | @@ -1150,10 +1157,10 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
417 | 1150 | _spawn_editor(cve_path) | 1157 | _spawn_editor(cve_path) |
418 | 1151 | elif action == 'unembargo': | 1158 | elif action == 'unembargo': |
419 | 1152 | if cve not in EmbargoList: | 1159 | if cve not in EmbargoList: |
421 | 1153 | raise ValueError('CVE %s is not in the embargo database (line %d):\n%s' % (cve, line_num, orig_line)) | 1160 | raise ValueError(f'CVE {cve} is not in the embargo database (line {line_num}):\n{orig_line}') |
422 | 1154 | 1161 | ||
423 | 1155 | if os.path.exists(os.path.join('active', cve)): | 1162 | if os.path.exists(os.path.join('active', cve)): |
425 | 1156 | raise ValueError('Cannot unembargo %s because it already exists in the active directory (line %d):\n%s' % (cve, line_num, orig_line)) | 1163 | raise ValueError(f'Cannot unembargo {cve} because it already exists in the active directory (line {line_num}):\n{orig_line}') |
426 | 1157 | 1164 | ||
427 | 1158 | if preprocess: | 1165 | if preprocess: |
428 | 1159 | continue | 1166 | continue |
429 | @@ -1164,7 +1171,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
430 | 1164 | try: | 1171 | try: |
431 | 1165 | reason = args[2] | 1172 | reason = args[2] |
432 | 1166 | except IndexError: | 1173 | except IndexError: |
434 | 1167 | raise ValueError('Invalid ignore command on line %d:\n%s' % (line_num, orig_line)) | 1174 | raise ValueError(f'Invalid ignore command on line {line_num}:\n{orig_line}') |
435 | 1168 | 1175 | ||
436 | 1169 | if preprocess: | 1176 | if preprocess: |
437 | 1170 | continue | 1177 | continue |
438 | @@ -1173,7 +1180,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
439 | 1173 | elif action == 'skip': | 1180 | elif action == 'skip': |
440 | 1174 | # If the CVE should be skipped, no arguments are allowed | 1181 | # If the CVE should be skipped, no arguments are allowed |
441 | 1175 | if len(args) > 2: | 1182 | if len(args) > 2: |
443 | 1176 | raise ValueError('Invalid skip command on line %d:\n%s' % (line_num, orig_line)) | 1183 | raise ValueError(f'Invalid skip command on line {line_num}:\n{orig_line}') |
444 | 1177 | 1184 | ||
445 | 1178 | if preprocess: | 1185 | if preprocess: |
446 | 1179 | continue | 1186 | continue |
447 | @@ -1181,7 +1188,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
448 | 1181 | self.skip_cve() | 1188 | self.skip_cve() |
449 | 1182 | else: | 1189 | else: |
450 | 1183 | # The second arg must be a known action | 1190 | # The second arg must be a known action |
452 | 1184 | raise ValueError('Unknown action (%s) on line %d:\n%s' % (action, line_num, orig_line)) | 1191 | raise ValueError(f'Unknown action ({action}) on line {line_num}:\n{orig_line}') |
453 | 1185 | 1192 | ||
454 | 1186 | def preprocess_cve(self, cve): | 1193 | def preprocess_cve(self, cve): |
455 | 1187 | desc = '' | 1194 | desc = '' |
456 | @@ -1195,20 +1202,20 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
457 | 1195 | desc += '# =================================end details==================================\n' | 1202 | desc += '# =================================end details==================================\n' |
458 | 1196 | # Display CVE information | 1203 | # Display CVE information |
459 | 1197 | if self.cve_data[cve]['public']: | 1204 | if self.cve_data[cve]['public']: |
461 | 1198 | desc += '# Published: %s\n' % (self.cve_data[cve]['public']) | 1205 | desc += f'# Published: {self.cve_data[cve]["public"]}\n' |
462 | 1199 | for ref in self.cve_data[cve]['refs']: | 1206 | for ref in self.cve_data[cve]['refs']: |
464 | 1200 | desc += '# %s: %s' % (ref[0], ref[1]) | 1207 | desc += f'# {ref[0]}: {ref[1]}' |
465 | 1201 | # Do not repeat URL if it matches the contents of the reference | 1208 | # Do not repeat URL if it matches the contents of the reference |
466 | 1202 | if ref[2] and ref[1].strip() != ref[2].strip(): | 1209 | if ref[2] and ref[1].strip() != ref[2].strip(): |
468 | 1203 | desc += ' %s' % (ref[2]) | 1210 | desc += f' {ref[2]}' |
469 | 1204 | desc += '\n' | 1211 | desc += '\n' |
470 | 1205 | for line in _wrap_desc(self.cve_data[cve]['desc']).split('\n'): | 1212 | for line in _wrap_desc(self.cve_data[cve]['desc']).split('\n'): |
472 | 1206 | desc += '# %s\n' % line | 1213 | desc += f'# {line}\n' |
473 | 1207 | if self.debian and cve in self.debian: | 1214 | if self.debian and cve in self.debian: |
475 | 1208 | desc += '# Debian CVE Tracker: %s\n' % (self.debian[cve]['state']) | 1215 | desc += f"# Debian CVE Tracker: {self.debian[cve]['state']}\n" |
476 | 1209 | if len(self.debian[cve]['note']): | 1216 | if len(self.debian[cve]['note']): |
477 | 1210 | for note in self.debian[cve]['note']: | 1217 | for note in self.debian[cve]['note']: |
479 | 1211 | desc += '# \t%s\n' % note | 1218 | desc += f'# \t{note}\n' |
480 | 1212 | for pkg in self.debian[cve]['pkgs']: | 1219 | for pkg in self.debian[cve]['pkgs']: |
481 | 1213 | info = [] | 1220 | info = [] |
482 | 1214 | if self.debian[cve]['pkgs'][pkg]['priority']: | 1221 | if self.debian[cve]['pkgs'][pkg]['priority']: |
483 | @@ -1222,7 +1229,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
484 | 1222 | answer = source_map.madison(source, pkg) | 1229 | answer = source_map.madison(source, pkg) |
485 | 1223 | for name in sorted(answer.keys()): | 1230 | for name in sorted(answer.keys()): |
486 | 1224 | for pkg in sorted(answer[name].keys()): | 1231 | for pkg in sorted(answer[name].keys()): |
488 | 1225 | desc += '# Ubuntu: %s | %s | %s\n' % (pkg, answer[name][pkg], name) | 1232 | desc += f'# Ubuntu: {pkg} | {answer[name][pkg]} | {name}\n' |
489 | 1226 | 1233 | ||
490 | 1227 | action = 'skip' | 1234 | action = 'skip' |
491 | 1228 | data = "" | 1235 | data = "" |
492 | @@ -1240,13 +1247,13 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
493 | 1240 | action = 'add' | 1247 | action = 'add' |
494 | 1241 | data = " ".join(self.debian[cve]['pkgs']) | 1248 | data = " ".join(self.debian[cve]['pkgs']) |
495 | 1242 | 1249 | ||
497 | 1243 | print('%s %s %s\n%s' % (action, cve, data, desc)) | 1250 | print(f'{action} {cve} {data}\n{desc}') |
498 | 1244 | 1251 | ||
499 | 1245 | def add_cve(self, cve, packages, priority=None): | 1252 | def add_cve(self, cve, packages, priority=None): |
500 | 1246 | # remove from not-for-us.txt if adding and ensure we remove any | 1253 | # remove from not-for-us.txt if adding and ensure we remove any |
501 | 1247 | # mistriaged_hint from the description | 1254 | # mistriaged_hint from the description |
502 | 1248 | if cve in CVEIgnoreNotForUsSet: | 1255 | if cve in CVEIgnoreNotForUsSet: |
504 | 1249 | cmd = ['sed', '-i', '/^%s #.*$/d' % cve, './ignored/not-for-us.txt'] | 1256 | cmd = ['sed', '-i', f'/^{cve} #.*$/d', './ignored/not-for-us.txt'] |
505 | 1250 | subprocess.call(cmd) | 1257 | subprocess.call(cmd) |
506 | 1251 | self.cve_data[cve]['desc'] = self.cve_data[cve]['desc'].replace(mistriaged_hint, '') | 1258 | self.cve_data[cve]['desc'] = self.cve_data[cve]['desc'].replace(mistriaged_hint, '') |
507 | 1252 | 1259 | ||
508 | @@ -1294,7 +1301,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
509 | 1294 | elif self.debian[cve]['pkgs'][pkg]['bug']: | 1301 | elif self.debian[cve]['pkgs'][pkg]['bug']: |
510 | 1295 | bug = self.debian[cve]['pkgs'][pkg]['bug'] | 1302 | bug = self.debian[cve]['pkgs'][pkg]['bug'] |
511 | 1296 | if bug: | 1303 | if bug: |
513 | 1297 | url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s" % bug | 1304 | url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=" + bug |
514 | 1298 | if url not in bug_urls: | 1305 | if url not in bug_urls: |
515 | 1299 | bug_urls.append(url) | 1306 | bug_urls.append(url) |
516 | 1300 | 1307 | ||
517 | @@ -1330,7 +1337,7 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
518 | 1330 | self.debian[cve]['pkgs'][pkg]['state']: | 1337 | self.debian[cve]['pkgs'][pkg]['state']: |
519 | 1331 | if re.search(r'^[0-9]', self.debian[cve]['pkgs'][pkg]['state']): | 1338 | if re.search(r'^[0-9]', self.debian[cve]['pkgs'][pkg]['state']): |
520 | 1332 | fixed_version = self.debian[cve]['pkgs'][pkg]['state'] | 1339 | fixed_version = self.debian[cve]['pkgs'][pkg]['state'] |
522 | 1333 | fixed_in = ",%s" % fixed_version | 1340 | fixed_in = f",{fixed_version}" |
523 | 1334 | 1341 | ||
524 | 1335 | # Now see if we can correlate this to an Ubuntu version | 1342 | # Now see if we can correlate this to an Ubuntu version |
525 | 1336 | answer = source_map.madison(source, pkg) | 1343 | answer = source_map.madison(source, pkg) |
526 | @@ -1344,20 +1351,20 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
527 | 1344 | if dpkg_compare_versions(version, 'ge', fixed_version): | 1351 | if dpkg_compare_versions(version, 'ge', fixed_version): |
528 | 1345 | if rel == cve_lib.devel_release: | 1352 | if rel == cve_lib.devel_release: |
529 | 1346 | rel = 'devel' | 1353 | rel = 'devel' |
531 | 1347 | fixed_in += ",%s,%s" % (rel, version) | 1354 | fixed_in += f",{rel},{version}" |
532 | 1348 | break | 1355 | break |
533 | 1349 | elif self.debian[cve]['pkgs'][pkg]['state'].startswith('<not-affected>') and \ | 1356 | elif self.debian[cve]['pkgs'][pkg]['state'].startswith('<not-affected>') and \ |
534 | 1350 | len(self.debian[cve]['pkgs'][pkg]['priority']) > 0: | 1357 | len(self.debian[cve]['pkgs'][pkg]['priority']) > 0: |
535 | 1351 | # capture that debian believes their version is unaffected | 1358 | # capture that debian believes their version is unaffected |
538 | 1352 | not_affected.append((pkg, "debian: %s" % self.debian[cve]['pkgs'][pkg]['priority'])) | 1359 | not_affected.append(pkg, f"debian: {self.debian[cve]['pkgs'][pkg]['priority']}") |
539 | 1353 | cmd += ['-p', "%s%s" % (pkg, fixed_in)] | 1360 | cmd += ['-p', f"{pkg}{fixed_in}"] |
540 | 1354 | 1361 | ||
541 | 1355 | subprocess.call(cmd) | 1362 | subprocess.call(cmd) |
542 | 1356 | for (pkg, reason) in not_affected: | 1363 | for (pkg, reason) in not_affected: |
543 | 1357 | cmd = ['./scripts/mass-cve-edit', '-p', pkg, '-r', 'upstream', '-s', 'not-affected', '-v', reason, cve] | 1364 | cmd = ['./scripts/mass-cve-edit', '-p', pkg, '-r', 'upstream', '-s', 'not-affected', '-v', reason, cve] |
544 | 1358 | subprocess.call(cmd) | 1365 | subprocess.call(cmd) |
545 | 1359 | self.num_added += 1 | 1366 | self.num_added += 1 |
547 | 1360 | return './active/%s' % cve | 1367 | return f'./active/{cve}' |
548 | 1361 | 1368 | ||
549 | 1362 | def unembargo_cve(self, cve): | 1369 | def unembargo_cve(self, cve): |
550 | 1363 | # unembargo a cve now public | 1370 | # unembargo a cve now public |
551 | @@ -1368,8 +1375,8 @@ class CVEHandler(xml.sax.handler.ContentHandler): | |||
552 | 1368 | # Append to ignore list unless is already in CVEIgnoreList and then | 1375 | # Append to ignore list unless is already in CVEIgnoreList and then |
553 | 1369 | # append to the ignored/ignore-mistriaged.txt | 1376 | # append to the ignored/ignore-mistriaged.txt |
554 | 1370 | txtfile = 'ignore-mistriaged.txt' if cve in CVEIgnoreNotForUsSet else 'not-for-us.txt' | 1377 | txtfile = 'ignore-mistriaged.txt' if cve in CVEIgnoreNotForUsSet else 'not-for-us.txt' |
557 | 1371 | with open('%s/ignored/%s' % (destdir, txtfile), 'a') as f: | 1378 | with open(f'{destdir}/ignored/{txtfile}', 'a') as f: |
558 | 1372 | f.write('%s # %s\n' % (cve, reason)) | 1379 | f.write(f'{cve} # {reason}\n') |
559 | 1373 | 1380 | ||
560 | 1374 | self.num_ignored += 1 | 1381 | self.num_ignored += 1 |
561 | 1375 | 1382 | ||
562 | @@ -1428,7 +1435,7 @@ if args.cve: | |||
563 | 1428 | continue | 1435 | continue |
564 | 1429 | # error out if is ignored | 1436 | # error out if is ignored |
565 | 1430 | if cve in CVEIgnoreList: | 1437 | if cve in CVEIgnoreList: |
567 | 1431 | print("%s already exists in UCT - please remove it then retriage." % cve) | 1438 | print(f"{cve} already exists in UCT - please remove it then retriage.") |
568 | 1432 | sys.exit(1) | 1439 | sys.exit(1) |
569 | 1433 | specific_cves.add(cve) | 1440 | specific_cves.add(cve) |
570 | 1434 | 1441 | ||
571 | @@ -1453,7 +1460,7 @@ if (args.import_missing_debian or args.mistriaged) and handler.debian is not Non | |||
572 | 1453 | 1460 | ||
573 | 1454 | 1461 | ||
574 | 1455 | for uri in args.uris: | 1462 | for uri in args.uris: |
576 | 1456 | print('Loading %s ...' % (uri), file=sys.stderr) | 1463 | print(f'Loading {uri} ...', file=sys.stderr) |
577 | 1457 | if '://' in uri: | 1464 | if '://' in uri: |
578 | 1458 | readable = urllib.request.urlopen(uri) | 1465 | readable = urllib.request.urlopen(uri) |
579 | 1459 | else: | 1466 | else: |
580 | @@ -1464,7 +1471,7 @@ for uri in args.uris: | |||
581 | 1464 | else: | 1471 | else: |
582 | 1465 | parser.parse(readable) | 1472 | parser.parse(readable) |
583 | 1466 | except xml.sax._exceptions.SAXParseException as e: | 1473 | except xml.sax._exceptions.SAXParseException as e: |
585 | 1467 | print("\n\nWARNING: %s is malformed:\n%s" % (uri, e)) | 1474 | print(f"\n\nWARNING: {uri} is malformed:\n{e}") |
586 | 1468 | print("Aborting", file=sys.stderr) | 1475 | print("Aborting", file=sys.stderr) |
587 | 1469 | sys.exit(1) | 1476 | sys.exit(1) |
588 | 1470 | print('') | 1477 | print('') |
589 | @@ -1490,17 +1497,17 @@ def refresh_cves(cve_refresh_list, full_refresh=True): | |||
590 | 1490 | cvsss = handler.cve_data[cve]['cvss'] | 1497 | cvsss = handler.cve_data[cve]['cvss'] |
591 | 1491 | except: | 1498 | except: |
592 | 1492 | if args.verbose: | 1499 | if args.verbose: |
594 | 1493 | print('%s not listed in XML' % (cve), file=sys.stderr) | 1500 | print(f'{cve} not listed in XML', file=sys.stderr) |
595 | 1494 | 1501 | ||
596 | 1495 | # Find the on-disk CVE file | 1502 | # Find the on-disk CVE file |
597 | 1496 | cvefile = "" | 1503 | cvefile = "" |
598 | 1497 | for status in ['active', 'retired', 'ignored']: | 1504 | for status in ['active', 'retired', 'ignored']: |
600 | 1498 | check = '%s/%s/%s' % (destdir, status, cve) | 1505 | check = f'{destdir}/{status}/{cve}' |
601 | 1499 | if os.path.exists(check): | 1506 | if os.path.exists(check): |
602 | 1500 | cvefile = check | 1507 | cvefile = check |
603 | 1501 | break | 1508 | break |
604 | 1502 | if cvefile == "": | 1509 | if cvefile == "": |
606 | 1503 | print('local dirs missing %s?!' % (cve), file=sys.stderr) | 1510 | print(f'local dirs missing {cve}?!', file=sys.stderr) |
607 | 1504 | continue | 1511 | continue |
608 | 1505 | 1512 | ||
609 | 1506 | # Load CVE | 1513 | # Load CVE |
610 | @@ -1524,14 +1531,14 @@ def refresh_cves(cve_refresh_list, full_refresh=True): | |||
611 | 1524 | if data['Description'].strip() != desc: | 1531 | if data['Description'].strip() != desc: |
612 | 1525 | cve_lib.update_multiline_field(cvefile, 'Description', desc) | 1532 | cve_lib.update_multiline_field(cvefile, 'Description', desc) |
613 | 1526 | updated = True | 1533 | updated = True |
615 | 1527 | debug("updated description for %s" % (cvefile)) | 1534 | debug(f"updated description for {cvefile}") |
616 | 1528 | 1535 | ||
617 | 1529 | # Update Publication Date if it needs it | 1536 | # Update Publication Date if it needs it |
618 | 1530 | if public: | 1537 | if public: |
619 | 1531 | if 'PublicDate' not in data or ('PublicDate' in data and data['PublicDate'] != public): | 1538 | if 'PublicDate' not in data or ('PublicDate' in data and data['PublicDate'] != public): |
620 | 1532 | cve_lib.update_field(cvefile, 'PublicDate', public) | 1539 | cve_lib.update_field(cvefile, 'PublicDate', public) |
621 | 1533 | updated = True | 1540 | updated = True |
623 | 1534 | debug("updated pubdate for %s" % (cvefile)) | 1541 | debug(f"updated pubdate for {cvefile}") |
624 | 1535 | 1542 | ||
625 | 1536 | # Add CVE Reference, if it's missing | 1543 | # Add CVE Reference, if it's missing |
626 | 1537 | if 'References' in data and re.match(r'^CVE-\d+-\d+$', cve): | 1544 | if 'References' in data and re.match(r'^CVE-\d+-\d+$', cve): |
627 | @@ -1539,19 +1546,19 @@ def refresh_cves(cve_refresh_list, full_refresh=True): | |||
628 | 1539 | if mitre_ref not in data['References']: | 1546 | if mitre_ref not in data['References']: |
629 | 1540 | cve_lib.add_reference(cvefile, mitre_ref) | 1547 | cve_lib.add_reference(cvefile, mitre_ref) |
630 | 1541 | updated = True | 1548 | updated = True |
632 | 1542 | debug("updated reference for %s" % (cvefile)) | 1549 | debug(f"updated reference for {cvefile}") |
633 | 1543 | 1550 | ||
634 | 1544 | # Update CVSS if needs it | 1551 | # Update CVSS if needs it |
635 | 1545 | for entry in cvsss: | 1552 | for entry in cvsss: |
636 | 1546 | try: | 1553 | try: |
637 | 1547 | updated |= cve_lib.add_cvss(cvefile, entry['source'], entry['vector']) | 1554 | updated |= cve_lib.add_cvss(cvefile, entry['source'], entry['vector']) |
639 | 1548 | debug("updated cvss for %s" % (cvefile)) | 1555 | debug(f"updated cvss for {cvefile}") |
640 | 1549 | except KeyError: | 1556 | except KeyError: |
641 | 1550 | # we might not have a vector, in this case continue | 1557 | # we might not have a vector, in this case continue |
642 | 1551 | pass | 1558 | pass |
643 | 1552 | 1559 | ||
644 | 1553 | if updated: | 1560 | if updated: |
646 | 1554 | print("Refreshed %s" % (cvefile), file=sys.stderr) | 1561 | print(f"Refreshed {cvefile}", file=sys.stderr) |
647 | 1555 | 1562 | ||
648 | 1556 | 1563 | ||
649 | 1557 | if args.refresh or args.score_refresh: | 1564 | if args.refresh or args.score_refresh: |
650 | @@ -1608,8 +1615,8 @@ for cve in new_cves: | |||
651 | 1608 | 1615 | ||
652 | 1609 | if not experimental: | 1616 | if not experimental: |
653 | 1610 | print('\n***********************************************************************') | 1617 | print('\n***********************************************************************') |
656 | 1611 | print(' %s (%d/%d: %d%%)' % (cve, count, total, (count * 100 / total))) | 1618 | print(f" {cve} ({count}/{total}: {int(count * 100 / total)}%)") |
657 | 1612 | print(' https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s' % (cve)) | 1619 | print(f" https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve}") |
658 | 1613 | print('***********************************************************************') | 1620 | print('***********************************************************************') |
659 | 1614 | handler.display_cve(cve, file=fout) | 1621 | handler.display_cve(cve, file=fout) |
660 | 1615 | (action, reason, packages) = handler.get_cve_suggestions(cve) | 1622 | (action, reason, packages) = handler.get_cve_suggestions(cve) |
661 | @@ -1619,16 +1626,16 @@ for cve in new_cves: | |||
662 | 1619 | else: | 1626 | else: |
663 | 1620 | line_prefix = '# ' | 1627 | line_prefix = '# ' |
664 | 1621 | 1628 | ||
666 | 1622 | fout.write('%s%s\n#\n' % (line_prefix, cve)) | 1629 | fout.write('{line_prefix}{cve}\n#\n') |
667 | 1623 | handler.display_cve(cve, file=fout, line_prefix=line_prefix, wrap_desc=True) | 1630 | handler.display_cve(cve, file=fout, line_prefix=line_prefix, wrap_desc=True) |
668 | 1624 | 1631 | ||
669 | 1625 | (action, reason, packages) = handler.get_cve_suggestions(cve) | 1632 | (action, reason, packages) = handler.get_cve_suggestions(cve) |
671 | 1626 | suggestion = '%s %s' % (cve, action) | 1633 | suggestion = f'{cve} {action}' |
672 | 1627 | if reason: | 1634 | if reason: |
674 | 1628 | suggestion += ' %s' % (reason) | 1635 | suggestion += f' {reason}' |
675 | 1629 | elif action == 'add': | 1636 | elif action == 'add': |
678 | 1630 | suggestion += ' untriaged %s' % (packages) | 1637 | suggestion += f' untriaged {packages}' |
679 | 1631 | fout.write('%s\n\n' % (suggestion)) | 1638 | fout.write(f'{suggestion}\n\n') |
680 | 1632 | 1639 | ||
681 | 1633 | if experimental: | 1640 | if experimental: |
682 | 1634 | fout.flush() | 1641 | fout.flush() |
683 | @@ -1636,7 +1643,7 @@ if experimental: | |||
684 | 1636 | assert((total == 0 and count == 0) or (total > 0 and count >= 0)) | 1643 | assert((total == 0 and count == 0) or (total > 0 and count >= 0)) |
685 | 1637 | # no need to spawn editor if no CVEs listed | 1644 | # no need to spawn editor if no CVEs listed |
686 | 1638 | if count > 0: | 1645 | if count > 0: |
688 | 1639 | prompt_user('Asking user to handle %d CVEs...' % count) | 1646 | prompt_user(f'Asking user to handle {count} CVEs...') |
689 | 1640 | _spawn_editor(fout.name) | 1647 | _spawn_editor(fout.name) |
690 | 1641 | else: | 1648 | else: |
691 | 1642 | prompt_user('Not spawning editor as no CVEs to process') | 1649 | prompt_user('Not spawning editor as no CVEs to process') |
692 | @@ -1645,8 +1652,7 @@ if experimental: | |||
693 | 1645 | handler.process_command_file(fout, preprocess=True) | 1652 | handler.process_command_file(fout, preprocess=True) |
694 | 1646 | break | 1653 | break |
695 | 1647 | except Exception as e: | 1654 | except Exception as e: |
698 | 1648 | print('Error encountered while processing the command file!', file=sys.stderr) | 1655 | print(f'Error encountered while processing the command file!\n{e}', file=sys.stderr) |
697 | 1649 | print('%s' % e, file=sys.stderr) | ||
699 | 1650 | print('Enter "quit" to lose all work or anything else to re-edit and try again: ', end='', file=sys.stderr) | 1656 | print('Enter "quit" to lose all work or anything else to re-edit and try again: ', end='', file=sys.stderr) |
700 | 1651 | sys.stderr.flush() | 1657 | sys.stderr.flush() |
701 | 1652 | response = sys.stdin.readline().strip().lower() | 1658 | response = sys.stdin.readline().strip().lower() |
These changes LGTM. Thanks for breaking down all your refactoring into reviewable changes!