aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/scripts/update-cwes.js
blob: 2264b2aff1059bcd5003a5b81acfdf495b9356dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * SonarQube
 * Copyright (C) 2009-2023 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
/* eslint-disable no-console */

/**
 * Execute this script by passing the path to the CWE XML definition file.
 *
 * You can download the full CWE database in XML format here: https://cwe.mitre.org/data/downloads.html
 * Make sure to unzip the downloaded file first before passing it to this script.
 *
 * Usage:
 *     node scripts/update-cwes.js PATH
 *   or:
 *     yarn update-cwes PATH
 *
 * Example:
 *     node scripts/update-cwes.js ~/Downloads/cwec_v4.6.xml
 *   or:
 *     yarn update-cwes ~/Downloads/cwec_v4.6.xml
 */

const fs = require('fs');
const chalk = require('chalk');
const jsdom = require('jsdom');
const { trim } = require('lodash');
const path = require('path');

const STANDARDS_JSON_FILE = path.join(
  __dirname,
  '..',
  'src',
  'main',
  'js',
  'helpers',
  'standards.json'
);

const xmlContent = readXMLContent(process.argv[2]);
const newCWEs = getCWEs(xmlContent);
writeToStandardsJson(newCWEs);

function readXMLContent(xmlPath) {
  if (fs.existsSync(xmlPath)) {
    try {
      fs.accessSync(xmlPath, fs.constants.R_OK);
      return fs.readFileSync(xmlPath).toString();
    } catch (e) {
      console.error(chalk.red(`No read access for XML file '${xmlPath}'`));
      throw e;
    }
  } else {
    console.error(chalk.red(`Cannot find XML file '${xmlPath}'`));
    throw Error('');
  }
}

function getCWEs(xml) {
  const document = new jsdom.JSDOM(xml);
  const weaknesses = document.window.document.querySelectorAll('Weaknesses Weakness');
  const cwes = {
    unknown: {
      title: 'No CWE associated'
    }
  };

  weaknesses.forEach(weakness => {
    const id = weakness.getAttribute('ID');
    const title = weakness.getAttribute('Name');
    let description = '';

    if (!id) {
      return;
    }

    if (!title) {
      console.log(chalk.yellow(`No Name attribute found for CWE '${id}'. Skipping.`));
      return;
    }

    const descriptionEl = weakness.querySelector('Description');
    if (descriptionEl) {
      description = trim(descriptionEl.textContent);
    }

    cwes[id] = { title, description };
  });

  return cwes;
}

function writeToStandardsJson(cwes) {
  try {
    fs.accessSync(STANDARDS_JSON_FILE, fs.constants.W_OK);
  } catch (e) {
    console.error(chalk.red(`No write access for standards.json ('${STANDARDS_JSON_FILE}') file`));
    throw e;
  }

  try {
    const json = JSON.parse(fs.readFileSync(STANDARDS_JSON_FILE).toString());
    json.cwe = cwes;
    fs.writeFileSync(STANDARDS_JSON_FILE, JSON.stringify(json, undefined, 2));
  } catch (e) {
    console.error(
      chalk.red(`Failed to write data to standards.json ('${STANDARDS_JSON_FILE}') file`)
    );
    throw e;
  }
}