Skip to content

Commit

Permalink
NEW: @W-15884203@: Create retire-js workspace scaffolding. Add build …
Browse files Browse the repository at this point in the history
…step to download vulnerabilities. (#21)
  • Loading branch information
stephen-carter-at-sf authored Jun 6, 2024
1 parent db2d29e commit 938e2de
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 0 deletions.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/code-analyzer-retirejs-engine/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vulnerabilities
14 changes: 14 additions & 0 deletions packages/code-analyzer-retirejs-engine/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
BSD 3-Clause License

Copyright (c) 2024, Salesforce.com, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* Downloads the latest version of RetireJS's internal catalog of JS vulnerabilities, then writes the resulting JSON to:
* dist/RetireJsVulns.json
*
* Usage: From the root folder of the project, run `node build-tools/updateRetireJsVulns.mjs`.
*/
import * as fs from 'fs';
import * as path from 'path';
import {fileURLToPath} from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const LATEST_VULN_FILE_URL = 'https://raw.githubusercontent.com/RetireJS/retire.js/master/repository/jsrepository.json';
const DESTINATION_DIR = path.join(__dirname, '..', 'vulnerabilities');
const DESTINATION_FILE = path.join(DESTINATION_DIR, 'RetireJsVulns.json');
const MIN_NUM_EXPECTED_VULNS = 300;

async function updateRetireJsVulns() {
try {
console.log(`Creating RetireJS vulnerability file`);

console.log(`* Downloading the latest RetireJS vulnerability file from: ${LATEST_VULN_FILE_URL}`);
const vulnJsonObj = await downloadJsonFile(LATEST_VULN_FILE_URL);

console.log(`* Validating the contents of the RetireJS vulnerability file`)
validateJson(vulnJsonObj);

console.log(`* Cleaning the contents of the RetireJS vulnerability file`);
cleanUpJson(vulnJsonObj);

console.log(`* Writing RetireJS vulnerability catalog to: ${DESTINATION_FILE}`)
await writeJson(vulnJsonObj);
console.log(`Success!`);

} catch (err) {
console.error(`Error creating catalog: ${err.message || err}`);
}
}

async function downloadJsonFile(jsonFileUrl) {
const response = await fetch(jsonFileUrl);
if (!response.ok) {
throw new Error(`Error downloading ${jsonFileUrl}. Status ${response.status}; ${response.statusText}`);
}
return await response.json();
}

function validateJson(vulnJsonObj) {
const problems = [];
let numVulnFound = 0;
for (const key of Object.keys(vulnJsonObj)) {
const value = vulnJsonObj[key];
if (!value.vulnerabilities || value.vulnerabilities.length === 0) {
continue;
}
value.vulnerabilities.forEach((vuln, i) => {
numVulnFound++;
if (!vuln.identifiers) {
problems.push(`Component: ${key}. Problem: Vulnerability #${i + 1} lacks identifiers.`);
}
if (!vuln.severity) {
problems.push(`Component: ${key}. Problem: Vulnerability #${i + 1} lacks a severity.`);
} else if (!["high","medium","low"].includes(vuln.severity)) {
problems.push(`Component: ${key}. Problem: Vulnerability #${i + 1} contains a severity that we currently do not support: ${vuln.severity}.`);
}
});
}
if (problems.length > 0) {
throw new Error(problems.join('\n'));
}
if (numVulnFound < MIN_NUM_EXPECTED_VULNS) {
throw new Error(`The number of vulnerabilities in the downloaded file was ${numVulnFound}, but we expected at least ${MIN_NUM_EXPECTED_VULNS}.`);
}
}

function cleanUpJson(vulnJsonObj) {
Object.keys(vulnJsonObj).forEach((key) => {
if (vulnJsonObj[key].extractors?.func) {
delete vulnJsonObj[key].extractors.func;
}
});
}

function writeJson(vulnJsonObj) {
if (!fs.existsSync(DESTINATION_DIR)) {
fs.mkdirSync(DESTINATION_DIR);
}
fs.writeFileSync(DESTINATION_FILE, JSON.stringify(vulnJsonObj, null, 2));
}

// Run the update process
updateRetireJsVulns();
14 changes: 14 additions & 0 deletions packages/code-analyzer-retirejs-engine/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
rules: {
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
}
}
);
65 changes: 65 additions & 0 deletions packages/code-analyzer-retirejs-engine/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"name": "@salesforce/code-analyzer-retirejs-engine",
"description": "Plugin package that adds 'retire-js' as an engine into Salesforce Code Analyzer",
"version": "0.1.0",
"author": "The Salesforce Code Analyzer Team",
"license": "BSD-3-Clause license",
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
"repository": {
"type": "git",
"url": "git+https://github.com/forcedotcom/code-analyzer-core.git",
"directory": "packages/code-analyzer-retirejs-engine"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"dependencies": {
"@salesforce/code-analyzer-engine-api": "0.2.0",
"@types/node": "^20.0.0"
},
"devDependencies": {
"@eslint/js": "^8.57.0",
"@types/jest": "^29.0.0",
"eslint": "^8.57.0",
"jest": "^29.0.0",
"rimraf": "*",
"ts-jest": "^29.0.0",
"typescript": "^5.4.5",
"typescript-eslint": "^7.8.0"
},
"engines": {
"node": ">=20.0.0"
},
"files": [
"dist",
"vulnerabilities",
"LICENSE",
"package.json"
],
"scripts": {
"prebuild": "node build-tools/updateRetireJsVulns.mjs",
"build": "tsc --build tsconfig.build.json --verbose",
"test": "jest --coverage",
"lint": "eslint src/**/*.ts",
"package": "npm pack",
"all": "npm run build && npm run test && npm run lint && npm run package",
"clean": "tsc --build tsconfig.build.json --clean",
"postclean": "rimraf dist && rimraf coverage && rimraf ./*.tgz && rimraf vulnerabilities",
"scrub": "npm run clean && rimraf node_modules",
"showcoverage": "open ./coverage/lcov-report/index.html"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"testMatch": [
"**/*.test.ts"
],
"testPathIgnorePatterns": [
"/node_modules/",
"/dist/"
],
"collectCoverageFrom": [
"src/**/*.ts",
"!src/index.ts"
]
}
}
Empty file.
6 changes: 6 additions & 0 deletions packages/code-analyzer-retirejs-engine/test/temp.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
describe('Temporary test', () => {
it('Temporary test', () => {
// This is needed to satisfy the build for now.
// This file will go away when we actually implement things.
});
});
12 changes: 12 additions & 0 deletions packages/code-analyzer-retirejs-engine/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": [
"./src",
"./vulnerabilities"
]
}
13 changes: 13 additions & 0 deletions packages/code-analyzer-retirejs-engine/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "./tsconfig.build.json",
"compilerOptions": {
"composite": true,
"outDir": "./dist",
"rootDir": "."
},
"include": [
"./src",
"./vulnerabilities",
"./test"
]
}

0 comments on commit 938e2de

Please sign in to comment.