From 9fa0daf247fffdcf21f7af489f6498f0cddb8a6d Mon Sep 17 00:00:00 2001 From: Siho Shin Date: Thu, 9 Jul 2026 03:24:36 +0900 Subject: asdf --- csv/critical.sh | 89 +++++++++++++++++++++++++++++++++++++ csv/sort.sh | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100755 csv/critical.sh create mode 100755 csv/sort.sh (limited to 'csv') diff --git a/csv/critical.sh b/csv/critical.sh new file mode 100755 index 0000000..ab20b34 --- /dev/null +++ b/csv/critical.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 doca-*-vuln.csv [more.csv ...]" >&2 + exit 1 +fi + +python3 - "$@" <<'PY' +import csv +import os +import re +import sys + +FILENAME_RE = re.compile( + r"^doca-(?P.+)-(?P\d+\.\d+\.\d+)-(?Phost|dpu)-vuln\.csv$" +) + +META_COLUMNS = ["doca_version", "doca_host", "doca_container"] + + +def parse_metadata(path): + base = os.path.basename(path) + match = FILENAME_RE.match(base) + + if not match: + raise ValueError( + f"Filename does not match expected pattern: {base}\n" + f"Expected: doca-(container)-(version)-(host)-vuln.csv" + ) + + return { + "doca_version": match.group("version"), + "doca_host": match.group("host"), + "doca_container": match.group("container"), + } + + +def is_critical(row): + fields_to_check = [ + "nvd_severity", + "severity", + "osv_severity", + ] + + for field in fields_to_check: + value = row.get(field, "") + if value and "CRITICAL" in value.upper(): + return True + + return False + + +def main(paths): + writer = None + output_header = None + + for path in paths: + metadata = parse_metadata(path) + + with open(path, "r", encoding="utf-8", newline="") as f: + reader = csv.DictReader(f) + + if reader.fieldnames is None: + continue + + if writer is None: + original_header = reader.fieldnames + output_header = META_COLUMNS + original_header + writer = csv.DictWriter( + sys.stdout, + fieldnames=output_header, + extrasaction="ignore", + ) + writer.writeheader() + + for row in reader: + if not is_critical(row): + continue + + output_row = {} + output_row.update(metadata) + output_row.update(row) + writer.writerow(output_row) + + +if __name__ == "__main__": + main(sys.argv[1:]) +PY diff --git a/csv/sort.sh b/csv/sort.sh new file mode 100755 index 0000000..1a025a4 --- /dev/null +++ b/csv/sort.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -lt 2 ]; then + echo "Usage: $0 doca-*-vuln.csv [more.csv ...]" >&2 + echo "Example: $0 doca doca-*-vuln.csv" >&2 + exit 1 +fi + +NAME="$1" +shift + +python3 - "$NAME" "$@" <<'PY' +import csv +import os +import re +import sys + +FILENAME_RE = re.compile( + r"^doca-(?P.+)-(?P\d+\.\d+\.\d+)-(?Phost|dpu)-vuln\.csv$" +) + +META_COLUMNS = ["doca_version", "doca_host", "doca_container"] + +OUTPUT_BUCKETS = [ + ("network", "nopriv"), + ("network", "priv"), + ("local", "nopriv"), + ("local", "priv"), +] + + +def parse_metadata(path): + base = os.path.basename(path) + match = FILENAME_RE.match(base) + + if not match: + raise ValueError( + f"Filename does not match expected pattern: {base}\n" + f"Expected: doca-(container)-(version)-(host)-vuln.csv" + ) + + return { + "doca_version": match.group("version"), + "doca_host": match.group("host"), + "doca_container": match.group("container"), + } + + +def get_av(row): + return ( + row.get("nvd_AV") + or row.get("AV") + or row.get("cvss_AV") + or "" + ).strip().upper() + + +def get_pr(row): + return ( + row.get("nvd_PR") + or row.get("PR") + or row.get("cvss_PR") + or "" + ).strip().upper() + + +def av_bucket(av): + # User requested N and A in the same file. + if av in {"N", "A"}: + return "network" + + return "local" + + +def pr_bucket(pr): + if pr == "N": + return "nopriv" + + # L, H, empty, unknown all go to privileged bucket. + return "priv" + + +def main(name, paths): + output_files = { + bucket: open(f"{name}-{bucket[0]}-{bucket[1]}.csv", "w", encoding="utf-8", newline="") + for bucket in OUTPUT_BUCKETS + } + + writers = {} + output_header = None + + try: + for path in paths: + metadata = parse_metadata(path) + + with open(path, "r", encoding="utf-8", newline="") as f: + reader = csv.DictReader(f) + + if reader.fieldnames is None: + continue + + if output_header is None: + original_header = reader.fieldnames + output_header = META_COLUMNS + original_header + + for bucket, fh in output_files.items(): + writer = csv.DictWriter( + fh, + fieldnames=output_header, + extrasaction="ignore", + ) + writer.writeheader() + writers[bucket] = writer + + for row in reader: + av = get_av(row) + pr = get_pr(row) + + bucket = (av_bucket(av), pr_bucket(pr)) + + output_row = {} + output_row.update(metadata) + output_row.update(row) + + writers[bucket].writerow(output_row) + + finally: + for fh in output_files.values(): + fh.close() + + +if __name__ == "__main__": + main(sys.argv[1], sys.argv[2:]) +PY -- cgit v1.2.3