🦆

【GAS】WindowsOSのバージョンとCVE情報を紐づけてみる(途中)

2025/03/21に公開

なぜ作成したのか

  • 昨日macOSで実装した機能をWindows側でも実装してみようという試み

技術スタック

やりたいこと

  • MSRCのAPIからWindowsOSのバージョン情報、関連CVE番号の情報を取得する
  • 登場するCVE番号についてNVDのAPIで詳細情報を取得する
  • AppsheetでOSバージョンとCVE情報を紐づけて見えるようにする

GAS(作成中)

  • APIを試し打ちしていて気が付いたが、あるAPIは値をJSON形式で返却するものの、あるAPIはXML形式で返却するという謎な仕様
// スクリプトプロパティからスプレッドシートIDを取得
const SPREADSHEET_ID = PropertiesService.getScriptProperties().getProperty('SPREADSHEET_ID');
const MSRC_API_UPDATES_URL = 'https://api.msrc.microsoft.com/cvrf/v3.0/updates/';

function main() {
  // Updateリストを取得
  const updateData = fetchMsrcUpdateData();
  const spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);

  updateWindowsVersionSheet(spreadsheet, updateData);

  // updateWindowsVersionSheet(spreadsheet, data);
  // updateWindowsVersionCVEsSheet(spreadsheet, data);
  // updateWindowsExploitedCVEsSheet(spreadsheet, data);
  // updateWorkCVEsSheet(spreadsheet, data);
  // updateCVEsSheet(spreadsheet);
}

function fetchMsrcUpdateData() {
  // 返り値はJSON形式
  const response = UrlFetchApp.fetch(MSRC_API_UPDATES_URL);
  return JSON.parse(response.getContentText());
}

function updateWindowsVersionSheet(spreadsheet, data) {
  const sheet = getOrCreateSheet(spreadsheet, 'WindowsVersion');
  sheet.clear();
  sheet.appendRow(['ID', 'Alias', 'DocumentTitle', 'Severity','InitialReleaseDate','CurrentReleaseDate', 'CvrfUrl']);

  const cveSheet = getOrCreateSheet(spreadsheet, 'WindowsVersion-CVEs');
  cveSheet.clear();
  cveSheet.appendRow(['id', 'CVE', 'ProductID']);

  const productSheet = getOrCreateSheet(spreadsheet, 'WindowsProduct');
  productSheet.clear();
  productSheet.appendRow(['ProductID', 'FullProductName']);

  data.value.forEach(entry => {
    sheet.appendRow([
      entry.ID || '',
      entry.Alias || '',
      entry.DocumentTitle || '',
      entry.Severity || '',
      entry.InitialReleaseDate || '',
      entry.CurrentReleaseDate || '',
      entry.CvrfUrl || ''
    ]);
    if(entry.CvrfUrl){
      // 返り値はXML形式
      const urlResponse = UrlFetchApp.fetch(entry.CvrfUrl);
      var xmlDoc = XmlService.parse(urlResponse.getContentText());
      var rootDoc = xmlDoc.getRootElement();
      updateWindowsVersionCVEsSheet(cveSheet,rootDoc,entry.ID);
    }
  });

}


function updateWindowsVersionCVEsSheet(sheet, data, id) {
  var ns = XmlService.getNamespace("vuln", "http://www.icasi.org/CVRF/schema/vuln/1.1");
  var vulnerabilitys  = data.getChildren("Vulnerability",ns);
  vulnerabilitys.forEach(entry => {
    var cve = entry.getChildren("CVE",ns)[0].getValue();
    var productIDs = entry.getChildren("ProductStatuses",ns)[0].getChildren("Status",ns)[0].getChildren("ProductID",ns);
    productIDs.forEach(pdata => {
      sheet.appendRow([
        id,
        cve,
        pdata.getValue()
      ])
    });
  }) ;
}

function updateWindowsProductSheet(sheet, data) {
(実装中)
}


function updateWindowsExploitedCVEsSheet(spreadsheet, data) {
(実装中)
}

function updateWorkWinCVEsSheet(spreadsheet, url) {
(実装中)
}

function updateCVEsSheet(spreadsheet) {
(実装中)
}

function getOrCreateSheet(spreadsheet, sheetName) {
  const sheet = spreadsheet.getSheetByName(sheetName);
  return sheet || spreadsheet.insertSheet(sheetName);
}

所感

  • XMLの罠に引っかかったため停滞中。もちろんJSON前提で実装してきたChatGPTくんには注意してみたものの、いい感じに改善されないので自前で実装してる
  • XMLの読みとき頑張る
GitHubで編集を提案

Discussion