Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ export async function activate(context: vscode.ExtensionContext) {
const diagnosticCollection =
vscode.languages.createDiagnosticCollection(extensionName);

// FIXME(MarshalX): works well on vscode open,
// but doesn't work when open another detection without closing the restored panel
// don't forget to register in context.subscriptions when will be fixed
// register "onWebviewPanel:detectionDetails" in activationEvents
// const detectionDetainsPanel = vscode.window.registerWebviewPanelSerializer(
// 'detectionDetails', new DetectionDetailsSerializer()
// );

const isAuthed = extensionContext.getGlobalState(VscodeStates.IsAuthorized);
extensionContext.setContext(VscodeStates.IsAuthorized, !!isAuthed);

Expand Down
39 changes: 36 additions & 3 deletions src/providers/code-actions/commonActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@ import {DiagnosticCode} from '../../services/common';
import {VscodeCommands} from '../../utils/commands';
import {CommandParameters} from '../../cli-wrapper/constants';
import {IgnoreCommandConfig} from '../../types/commands';
import {scanResultsService} from '../../services/ScanResultsService';

export const createIgnoreRuleAction = (
diagnostics: vscode.Diagnostic[], diagnosticCode: DiagnosticCode, document: vscode.TextDocument
): vscode.CodeAction => {
const detection = scanResultsService.getDetectionById(diagnosticCode.uniqueDetectionId);
const ruleId = detection?.detection_rule_id;

const ignoreRuleAction = new vscode.CodeAction(
`ignore rule ${diagnosticCode.ruleId}`,
`ignore rule ${ruleId}`,
vscode.CodeActionKind.QuickFix
);
ignoreRuleAction.command = {
command: VscodeCommands.IgnoreCommandId,
title: `Ignore rule ID: ${diagnosticCode.ruleId}`,
title: `Ignore rule ID: ${ruleId}`,
tooltip: 'This will always ignore this rule type',
arguments: [
{
scanType: diagnosticCode.scanType,
ignoreBy: CommandParameters.ByRule,
param: diagnosticCode.ruleId,
param: ruleId,
document: document,
} as IgnoreCommandConfig,
],
Expand Down Expand Up @@ -56,3 +60,32 @@ export const createIgnorePathAction = (
return ignorePathAction;
};

export const createOpenViolationCardAction = (
diagnostics: vscode.Diagnostic[], diagnosticCode: DiagnosticCode
): vscode.CodeAction => {
const detection = scanResultsService.getDetectionById(diagnosticCode.uniqueDetectionId);

let message = detection?.message;
if (message && message.length > 50) {
message = message.slice(0, 50) + '...';
}

const openViolationCardAction = new vscode.CodeAction(
`open violation card for ${message}`,
vscode.CodeActionKind.QuickFix
);
openViolationCardAction.command = {
command: VscodeCommands.OpenViolationPanel,
title: `Open Violation Card: ${message}`,
tooltip: 'This will open violation card for this detection',
arguments: [
diagnosticCode.scanType,
detection,
],
};
openViolationCardAction.diagnostics = diagnostics;
openViolationCardAction.isPreferred = true;

return openViolationCardAction;
};

3 changes: 2 additions & 1 deletion src/providers/code-actions/iacCodeActions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as vscode from 'vscode';
import {DiagnosticCode} from '../../services/common';
import {createIgnorePathAction, createIgnoreRuleAction} from './commonActions';
import {createIgnorePathAction, createIgnoreRuleAction, createOpenViolationCardAction} from './commonActions';

export const createCommandCodeActions = (
document: vscode.TextDocument,
diagnostics: vscode.Diagnostic[],
diagnosticCode: DiagnosticCode,
): vscode.CodeAction[] => {
return [
createOpenViolationCardAction(diagnostics, diagnosticCode),
createIgnoreRuleAction(diagnostics, diagnosticCode, document),
createIgnorePathAction(diagnostics, diagnosticCode, document),
];
Expand Down
3 changes: 2 additions & 1 deletion src/providers/code-actions/sastCodeActions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as vscode from 'vscode';
import {DiagnosticCode} from '../../services/common';
import {createIgnorePathAction, createIgnoreRuleAction} from './commonActions';
import {createIgnorePathAction, createIgnoreRuleAction, createOpenViolationCardAction} from './commonActions';

export const createCommandCodeActions = (
document: vscode.TextDocument,
diagnostics: vscode.Diagnostic[],
diagnosticCode: DiagnosticCode,
): vscode.CodeAction[] => {
return [
createOpenViolationCardAction(diagnostics, diagnosticCode),
createIgnoreRuleAction(diagnostics, diagnosticCode, document),
createIgnorePathAction(diagnostics, diagnosticCode, document),
];
Expand Down
3 changes: 2 additions & 1 deletion src/providers/code-actions/scaCodeActions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as vscode from 'vscode';
import {DiagnosticCode} from '../../services/common';
import {createIgnorePathAction, createIgnoreRuleAction} from './commonActions';
import {createIgnorePathAction, createIgnoreRuleAction, createOpenViolationCardAction} from './commonActions';

export const createCommandCodeActions = (
document: vscode.TextDocument,
diagnostics: vscode.Diagnostic[],
diagnosticCode: DiagnosticCode,
): vscode.CodeAction[] => {
return [
createOpenViolationCardAction(diagnostics, diagnosticCode),
createIgnoreRuleAction(diagnostics, diagnosticCode, document),
createIgnorePathAction(diagnostics, diagnosticCode, document),
];
Expand Down
3 changes: 2 additions & 1 deletion src/providers/code-actions/secretsCodeActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {DiagnosticCode} from '../../services/common';
import {VscodeCommands} from '../../utils/commands';
import {CommandParameters} from '../../cli-wrapper/constants';
import {IgnoreCommandConfig} from '../../types/commands';
import {createIgnorePathAction, createIgnoreRuleAction} from './commonActions';
import {createIgnorePathAction, createIgnoreRuleAction, createOpenViolationCardAction} from './commonActions';
import {ScanType} from '../../constants';

const createIgnoreValueAction = (
Expand Down Expand Up @@ -41,6 +41,7 @@ export const createCommandCodeActions = (
diagnosticCode: DiagnosticCode,
): vscode.CodeAction[] => {
return [
createOpenViolationCardAction(diagnostics, diagnosticCode),
createIgnoreValueAction(diagnostics, range, document),
createIgnoreRuleAction(diagnostics, diagnosticCode, document),
createIgnorePathAction(diagnostics, diagnosticCode, document),
Expand Down
52 changes: 52 additions & 0 deletions src/services/ScanResultsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as crypto from 'crypto';
import {getWorkspaceState, updateWorkspaceState} from '../utils/context';
import {AnyDetection} from '../types/detection';

const _STORAGE_KEY_PREFIX = 'CS:';

export const calculateUniqueDetectionId = (detection: AnyDetection): string => {
const hash = crypto.createHash('sha256');

const detectionJson = JSON.stringify(detection);
hash.update(detectionJson);

const hexHash = hash.digest('hex');
const shortHashLength = Math.ceil(hexHash.length / 4); // 2 ** 64 combinations
return hexHash.slice(0, shortHashLength);
};

class ScanResultsService {
public getDetectionById(detectionId: string): AnyDetection | undefined {
const value = getWorkspaceState(detectionId);
if (!value) {
return undefined;
}

return getWorkspaceState(detectionId) as AnyDetection;
}

public getDetections(scanType: string): AnyDetection[] {
const scanTypeKey = `${_STORAGE_KEY_PREFIX}${scanType}`;
return getWorkspaceState(scanTypeKey) as AnyDetection[] || [];
}

public saveDetections(scanType: string, detections: AnyDetection[]): void {
detections.forEach((detection) => {
this.saveDetection(scanType, detection);
});
}

public saveDetection(scanType: string, detection: AnyDetection): void {
const scanTypeKey = `${_STORAGE_KEY_PREFIX}${scanType}`;

const detections = getWorkspaceState(scanTypeKey) as AnyDetection[] || [];
detections.push(detection);

updateWorkspaceState(scanTypeKey, detections);

const uniqueDetectionKey = calculateUniqueDetectionId(detection);
updateWorkspaceState(uniqueDetectionKey, detection);
}
}

export const scanResultsService = new ScanResultsService();
8 changes: 4 additions & 4 deletions src/services/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ export const finalizeScanState = (state: VscodeStates, success: boolean, progres

export class DiagnosticCode {
scanType: string;
ruleId: string;
uniqueDetectionId: string;

constructor(scanType: ScanType, ruleId: string) {
constructor(scanType: ScanType, uniqueDetectionId: string) {
this.scanType = scanType;
this.ruleId = ruleId;
this.uniqueDetectionId = uniqueDetectionId;
}

toString(): string {
return `${this.scanType}${DIAGNOSTIC_CODE_SEPARATOR}${this.ruleId}`;
return `${this.scanType}${DIAGNOSTIC_CODE_SEPARATOR}${this.uniqueDetectionId}`;
}

static fromString(diagnosticCode: string): DiagnosticCode {
Expand Down
5 changes: 4 additions & 1 deletion src/services/scanners/IacScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {refreshTreeViewData} from '../../providers/tree-view/utils';
import {TreeView} from '../../providers/tree-view/types';
import {ScanType} from '../../constants';
import {VscodeStates} from '../../utils/states';
import {calculateUniqueDetectionId, scanResultsService} from '../ScanResultsService';

interface IacScanParams {
pathToScan: string;
Expand Down Expand Up @@ -176,7 +177,7 @@ const detectionsToDiagnostics = async (
);

diagnostic.source = extensionId;
diagnostic.code = new DiagnosticCode(ScanType.Iac, detection.detection_rule_id).toString();
diagnostic.code = new DiagnosticCode(ScanType.Iac, calculateUniqueDetectionId(detection)).toString();

result[documentPath] = result[documentPath] || [];
result[documentPath].push(diagnostic);
Expand Down Expand Up @@ -204,6 +205,8 @@ const handleScanDetections = async (
TrayNotifications.showProblemsDetection(detections.length, ScanType.Iac);
}

scanResultsService.saveDetections(ScanType.Iac, detections);

refreshTreeViewData({
detections,
treeView: treeView,
Expand Down
5 changes: 4 additions & 1 deletion src/services/scanners/SastScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {refreshTreeViewData} from '../../providers/tree-view/utils';
import {TreeView} from '../../providers/tree-view/types';
import {ScanType} from '../../constants';
import {VscodeStates} from '../../utils/states';
import {calculateUniqueDetectionId, scanResultsService} from '../ScanResultsService';

interface SastScanParams {
pathToScan: string;
Expand Down Expand Up @@ -167,7 +168,7 @@ const detectionsToDiagnostics = async (
);

diagnostic.source = extensionId;
diagnostic.code = new DiagnosticCode(ScanType.Sast, detection.detection_rule_id).toString();
diagnostic.code = new DiagnosticCode(ScanType.Sast, calculateUniqueDetectionId(detection)).toString();

result[documentPath] = result[documentPath] || [];
result[documentPath].push(diagnostic);
Expand Down Expand Up @@ -195,6 +196,8 @@ const handleScanDetections = async (
TrayNotifications.showProblemsDetection(detections.length, ScanType.Sast);
}

scanResultsService.saveDetections(ScanType.Sast, detections);

refreshTreeViewData({
detections,
treeView: treeView,
Expand Down
14 changes: 7 additions & 7 deletions src/services/scanners/ScaScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ import * as vscode from 'vscode';
import {extensionOutput} from '../../logging/extension-output';
import {cliWrapper} from '../../cli-wrapper/cli-wrapper';
import statusBar from '../../utils/status-bar';
import {extensionId, StatusBarTexts} from '../../utils/texts';
import {
StatusBarTexts,
extensionId,
} from '../../utils/texts';
import {
finalizeScanState,
DiagnosticCode,
finalizeScanState,
updateDetectionState,
validateCliCommonErrors,
validateCliCommonScanErrors,
updateDetectionState,
} from '../common';
import {getWorkspaceState, updateWorkspaceState} from '../../utils/context';
import {ScaDetection} from '../../types/detection';
Expand All @@ -22,6 +19,7 @@ import {TreeView} from '../../providers/tree-view/types';
import {refreshTreeViewData} from '../../providers/tree-view/utils';
import {getPackageFileForLockFile, isSupportedLockFile, ScanType} from '../../constants';
import {VscodeStates} from '../../utils/states';
import {calculateUniqueDetectionId, scanResultsService} from '../ScanResultsService';

interface ScaScanParams {
pathToScan: string;
Expand Down Expand Up @@ -143,7 +141,7 @@ const detectionsToDiagnostics = async (
);

diagnostic.source = extensionId;
diagnostic.code = new DiagnosticCode(ScanType.Sca, detection.detection_rule_id).toString();
diagnostic.code = new DiagnosticCode(ScanType.Sca, calculateUniqueDetectionId(detection)).toString();

result[file_name] = result[file_name] || [];
result[file_name].push(diagnostic);
Expand Down Expand Up @@ -179,6 +177,8 @@ const handleScanDetections = async (
TrayNotifications.showProblemsDetection(result.detections.length, ScanType.Sca);
}

scanResultsService.saveDetections(ScanType.Sca, detections);

refreshTreeViewData({
detections,
treeView,
Expand Down
11 changes: 7 additions & 4 deletions src/services/scanners/SecretScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {cliWrapper} from '../../cli-wrapper/cli-wrapper';
import statusBar from '../../utils/status-bar';
import {extensionId, StatusBarTexts, TrayNotificationTexts} from '../../utils/texts';
import {
finalizeScanState,
DiagnosticCode,
finalizeScanState,
updateDetectionState,
validateCliCommonErrors,
validateCliCommonScanErrors,
updateDetectionState,
} from '../common';
import {getWorkspaceState, updateWorkspaceState} from '../../utils/context';
import {SecretDetection} from '../../types/detection';
Expand All @@ -19,6 +19,7 @@ import {refreshTreeViewData} from '../../providers/tree-view/utils';
import {TreeView} from '../../providers/tree-view/types';
import {ScanType} from '../../constants';
import {VscodeStates} from '../../utils/states';
import {calculateUniqueDetectionId, scanResultsService} from '../ScanResultsService';

interface SecretScanParams {
pathToScan: string;
Expand Down Expand Up @@ -141,7 +142,7 @@ const detectionsToDiagnostics = async (
);
const endPosition = document?.positionAt(
detection.detection_details.start_position +
detection.detection_details.length
detection.detection_details.length
);

if (!startPosition || !endPosition) {
Expand All @@ -163,7 +164,7 @@ const detectionsToDiagnostics = async (
);

diagnostic.source = extensionId;
diagnostic.code = new DiagnosticCode(ScanType.Secrets, detection.detection_rule_id).toString();
diagnostic.code = new DiagnosticCode(ScanType.Secrets, calculateUniqueDetectionId(detection)).toString();

result[documentPath] = result[documentPath] || [];
result[documentPath].push(diagnostic);
Expand Down Expand Up @@ -195,6 +196,8 @@ const handleScanDetections = async (
TrayNotifications.showProblemsDetection(result.detections.length, ScanType.Secrets);
}

scanResultsService.saveDetections(ScanType.Secrets, detections);

refreshTreeViewData({
detections,
treeView: treeView,
Expand Down