CVE-2022-4942: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability was found in mportuga eslint-detailed-reporter up to 0.9.0 and classified as problematic. Affected by this issue is the function renderIssue in the library lib/template-generator.js. The manipulation of the argument message leads to cross site scripting. The attack may be launched remotely. The patch is identified as 505c190efd4905990db6207863bdcbd9b1d7e1bd. It is recommended to apply a patch to fix this issue. VDB-226310 is the identifier assigned to this vulnerability.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-04-20T06:15Z
Repository: https://github.com/mportuga/eslint-detailed-reporter
Language: JavaScript
Files changed: lib/template-generator.js
Commit date: 2022-06-02 06:36:31 -0400
Commit message: fix(template-generator): fix xss problem in issue message

- use `_.escape` for html escape instead of `formatSourceCode`
- escape issue message when rendering issues\
   e.g. rule 'vue/no-lone-template' produces
   message '`<template>` require directive.'

Diff: diff --git a/lib/template-generator.js b/lib/template-generator.js
index 0134695..d25ed34 100644
--- a/lib/template-generator.js
+++ b/lib/template-generator.js
@@ -145,11 +145,11 @@ function renderIssue(message) {
 	return issueTemplate({
 		severity: severityString(message.severity),
 		severityName: message.severity === 1 ? 'Warning' : 'Error',
 		lineNumber: message.line,
 		column: message.column,
-		message: message.message,
+		message: _.escape(message.message),
 		ruleId: message.ruleId,
 		ruleLink: getRuleLink(message.ruleId)
 	});
 }
 
@@ -204,19 +204,10 @@ function renderResultDetails(sourceCode, messages, parentIndex) {
 			issues: _.map(messages, renderIssue).join('')
 		})
 	});
 }
 
-/**
- * Formats the source code before adding it to the HTML
- * @param {string} sourceCode Source code string
- * @returns {string} Source code string which will not cause issues in the HTML
- */
-function formatSourceCode(sourceCode) {
-	return sourceCode.replace(/</g, '&#60;').replace(/>/g, '&#62;');
-}
-
 /**
  * Creates the test results HTML
  * @param {Array} results Test results.
  * @param {String} currDir Current working directory
  * @returns {string} HTML string describing the results.
@@ -233,11 +224,11 @@ function renderResults(results, currDir) {
 		});
 
 		// only renders the source code if there are issues present in the file
 		if (!_.isEmpty(result.messages)) {
 			// reads the file to get the source code if the source is not provided
-			const sourceCode = formatSourceCode(result.source || fs.readFileSync(result.filePath, 'utf8'));
+			const sourceCode = _.escape(result.source || fs.readFileSync(result.filePath, 'utf8'));
 
 			template += renderResultDetails(sourceCode, result.messages, index);
 		}
 
 		return template;
@@ -377,6 +368,6 @@ module.exports.generateTemplate = function generateTemplate(results, isMultiOn)
 		summaryDetails: renderSummaryDetails(rules, problemFiles, currWorkingDir),
 		results: renderResults(results, currWorkingDir),
 		styles: isMultiOn && isOutputDirKnown() ? '<link rel="stylesheet" href="./styles.css">' : styles(),
 		scripts: isMultiOn && isOutputDirKnown() ? '<script type="text/javascript" src="./main.js"></script>' : scripts()
 	});
-};
\ No newline at end of file
+};

Vulnerable code: 		message: message.message,
/**
 * Formats the source code before adding it to the HTML
 * @param {string} sourceCode Source code string
 * @returns {string} Source code string which will not cause issues in the HTML
 */
function formatSourceCode(sourceCode) {
	return sourceCode.replace(/</g, '&#60;').replace(/>/g, '&#62;');
}

			const sourceCode = formatSourceCode(result.source || fs.readFileSync(result.filePath, 'utf8'));
};
Fixed code: 		message: _.escape(message.message),
			const sourceCode = _.escape(result.source || fs.readFileSync(result.filePath, 'utf8'));
};