diff --git a/src/snyk/snykCode/utils/htmlEncoder.ts b/src/snyk/snykCode/utils/htmlEncoder.ts
new file mode 100644
index 000000000..c17f4d94a
--- /dev/null
+++ b/src/snyk/snykCode/utils/htmlEncoder.ts
@@ -0,0 +1,16 @@
+import he from 'he';
+import { ExampleCommitFix } from '../../common/languageServer/types';
+
+export const encodeExampleCommitFixes = (exampleCommitFixes: ExampleCommitFix[]): ExampleCommitFix[] => {
+ return exampleCommitFixes.map(exampleCommitFixes => {
+ return {
+ ...exampleCommitFixes,
+ lines: exampleCommitFixes.lines.map(line => {
+ return {
+ ...line,
+ line: he.encode(line.line),
+ };
+ }),
+ };
+ });
+};
diff --git a/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts b/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts
index 616ef14f0..bffd67f56 100644
--- a/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts
+++ b/src/snyk/snykCode/views/suggestion/codeSuggestionWebviewProvider.ts
@@ -1,4 +1,3 @@
-import he from 'he';
import _ from 'lodash';
import * as vscode from 'vscode';
import {
@@ -22,6 +21,7 @@ import { IVSCodeWorkspace } from '../../../common/vscode/workspace';
import { WEBVIEW_PANEL_QUALITY_TITLE, WEBVIEW_PANEL_SECURITY_TITLE } from '../../constants/analysis';
import { messages as errorMessages } from '../../messages/error';
import { getAbsoluteMarkerFilePath } from '../../utils/analysisUtils';
+import { encodeExampleCommitFixes } from '../../utils/htmlEncoder';
import { IssueUtils } from '../../utils/issueUtils';
import { ICodeSuggestionWebviewProvider } from '../interfaces';
@@ -113,12 +113,7 @@ export class CodeSuggestionWebviewProvider
this.registerListeners();
}
- issue.additionalData.exampleCommitFixes.map(ecf => {
- return ecf.lines.map(l => {
- l.line = he.encode(l.line);
- return l;
- });
- });
+ issue.additionalData.exampleCommitFixes = encodeExampleCommitFixes(issue.additionalData.exampleCommitFixes);
this.panel.webview.html = this.getHtmlForWebview(this.panel.webview);
this.panel.iconPath = vscode.Uri.joinPath(
diff --git a/src/test/unit/snykCode/helpers.test.ts b/src/test/unit/snykCode/helpers.test.ts
new file mode 100644
index 000000000..595e454c3
--- /dev/null
+++ b/src/test/unit/snykCode/helpers.test.ts
@@ -0,0 +1,70 @@
+import { strictEqual } from 'assert';
+import { ExampleCommitFix } from '../../../snyk/common/languageServer/types';
+import { encodeExampleCommitFixes } from '../../../snyk/snykCode/utils/htmlEncoder';
+
+const exampleInput: ExampleCommitFix[] = [
+ {
+ commitURL:
+ 'https://github.com/hiddentao/fast-levenshtein/commit/8d67bde78c9e75b5e253b0e84d0cbf227ffb98f9?diff=split#diff-a58852f173bee316460a26934b8a3c4d79b1acb88af655346ae74adce78113f7L-1',
+ lines: [
+ {
+ line: '\t\t\t\t\tuploadUserPicture(req.user.uid, req.files.userPhoto.name, req.files.userPhoto.path, res);\n',
+ lineNumber: 101,
+ lineChange: 'removed',
+ },
+ {
+ line: " files.map(file => path.join(...[dashboardAppPath].concat(file.fileName.split('/'))))\n",
+ lineNumber: 145,
+ lineChange: 'added',
+ },
+ ],
+ },
+ {
+ commitURL:
+ 'https://github.com/guzzle/guzzle/commit/3d499a1b7ce589c3ef39d78bb1730d83d8a89c79?diff=split#diff-dea67d130560147fa1eeb821ab305ce5c0d44c5a3a0b16f3f11b4cb48008dcbaL-1',
+ lines: [
+ {
+ line: "\tvar template = routes['/' + req.params.path] || routes['/'];\n",
+ lineNumber: 43,
+ lineChange: 'added',
+ },
+ {
+ line: "\t\t\tconsole.log('Info: Attempting upload to: '+ uploadPath);\n",
+ lineNumber: 130,
+ lineChange: 'none',
+ },
+ ],
+ },
+ {
+ commitURL: 'https://github.com/example/security-fix/commit/1234567890abcdef?diff=split#diff-securityL-1',
+ lines: [
+ {
+ line: `'that.responses = eval('('+ request.body + ')');\n'`, // Potential security vulnerability: eval with user input
+ lineNumber: 50,
+ lineChange: 'removed',
+ },
+ ],
+ },
+];
+
+suite('encodeExampleCommitFixes', () => {
+ test('should encode lines', () => {
+ // The `he` library encodes characters into their hexadecimal numeric character reference.
+ const encodedResults = encodeExampleCommitFixes(exampleInput);
+
+ strictEqual(
+ encodedResults[0].lines[0].line,
+ ' uploadUserPicture(req.user.uid, req.files.userPhoto.name, req.files.userPhoto.path, res);\n',
+ );
+
+ strictEqual(
+ encodedResults[0].lines[1].line,
+ ' files.map(file => path.join(...[dashboardAppPath].concat(file.fileName.split('/'))))\n',
+ );
+
+ strictEqual(
+ encodedResults[2].lines[0].line,
+ ''that.responses = eval('('+ request.body + ')');\n' + ''',
+ );
+ });
+});