Created
September 11, 2025 00:48
-
-
Save blacknon/3e01945bde0e811168384d81653aefa3 to your computer and use it in GitHub Desktop.
CVE-IDから必要な情報だけ引っ張ってきてTSVにする簡易スクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- encoding: UTF-8 -*- | |
# | |
# Description: CVEIDの情報をAPIから取得して加工するスクリプト。 | |
# エラーチェックもろくにしていないガバガバスクリプト。 | |
# ============================================= | |
import argparse | |
import sys | |
import select | |
import requests | |
def is_pipe() -> bool: | |
"""is_pipe | |
本スクリプトがパイプから値を受け取っているか否かを確認する | |
""" | |
if select.select([sys.stdin, ], [], [], 0.0)[0]: | |
return True | |
return False | |
def get_cve_from_nvdapi(cveid: str): | |
"""NVD APIからCVE情報を取得し、v3/v2のスコアをTSV形式で返す | |
- v3系とv2系をそれぞれ1行ずつ | |
- Primary/SecondaryのうちbaseScoreが高い方を採用 | |
""" | |
uri = f'https://services.nvd.nist.gov/rest/json/cves/2.0/?cveId={cveid}' | |
response = requests.get(uri, timeout=30) | |
data = response.json() | |
if not data.get('vulnerabilities'): | |
raise ValueError(f"CVE {cveid} not found") | |
cve_info = data['vulnerabilities'][0]['cve'] | |
cve_id = cve_info['id'] | |
published = cve_info.get('published', "") | |
url = None | |
if cve_info.get("references"): | |
url = cve_info["references"][0].get("url") | |
if not url: | |
url = f"https://nvd.nist.gov/vuln/detail/{cve_id}" | |
rows = [] | |
metrics = cve_info.get("metrics", {}) | |
# ---- CVSS v3.x ---- | |
v3_metrics = metrics.get("cvssMetricV31", []) | |
if v3_metrics: | |
# baseScore の降順で最大のものを採用 | |
best_v3 = max(v3_metrics, key=lambda m: m["cvssData"]["baseScore"]) | |
cvssData = best_v3["cvssData"] | |
rows.append([ | |
cve_id, | |
best_v3.get("source", ""), | |
cvssData.get("version", ""), | |
cvssData.get("baseSeverity", best_v3.get("baseSeverity", "")), | |
str(cvssData.get("baseScore", "")), | |
published, | |
url | |
]) | |
# ---- CVSS v2.x ---- | |
v2_metrics = metrics.get("cvssMetricV2", []) | |
if v2_metrics: | |
best_v2 = max(v2_metrics, key=lambda m: m["cvssData"]["baseScore"]) | |
cvssData = best_v2["cvssData"] | |
rows.append([ | |
cve_id, | |
best_v2.get("source", ""), | |
cvssData.get("version", ""), | |
best_v2.get("baseSeverity", ""), | |
str(cvssData.get("baseScore", "")), | |
published, | |
url | |
]) | |
# TSV文字列に変換(ヘッダ付き) | |
header = ["CVE-ID", "CVSS付与機関", "CVSSのバージョン", "脅威度スコア", "ベーススコア", "情報公開日", "URL"] | |
lines = ["\t".join(header)] | |
for row in rows: | |
lines.append("\t".join(row)) | |
return "\n".join(lines) | |
def main(): | |
parser = argparse.ArgumentParser(description="CVE情報を標準入力で受け付けてTSVにして出力する") | |
parser.add_argument("cveid", nargs="?", help="CVEID。複数指定する場合はスペース区切り。指定しなければ標準入力を使う") | |
parser.add_argument("--format", "-f", help="フォーマット") | |
args = parser.parse_args() | |
# 入力の取得 | |
if args.cveid is not None: | |
cveid = args.cveid | |
else: | |
# pipeか否かで処理を切り替え | |
if is_pipe(): | |
stdin = input() | |
cveid = stdin | |
else: | |
print("情報を取得するCVEIDを引数で渡すか、標準入力で渡してください.", file=sys.stderr) | |
sys.exit(1) | |
data = get_cve_from_nvdapi(cveid) | |
print(data) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment