Skip to content

Commit

Permalink
CM-43066 - Add the "Ignore this violation" button for violation card …
Browse files Browse the repository at this point in the history
…of SCA (#122)
  • Loading branch information
MarshalX authored Dec 19, 2024
1 parent 77950fa commit 2d227be
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 27 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Unreleased]

## [v1.14.0]

- Add the "Ignore this violation" button for violation card of SCA
- Add support of `.gitignore` files for a file excluding from scans

## [v1.13.1]

- Improve suggested AI fix rendering in violation cards
Expand Down Expand Up @@ -130,6 +135,8 @@

The first stable release with the support of Secrets, SCA, TreeView, Violation Card, and more.

[v1.14.0]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.14.0

[v1.13.1]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.13.1

[v1.13.0]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.13.0
Expand Down Expand Up @@ -178,4 +185,4 @@ The first stable release with the support of Secrets, SCA, TreeView, Violation C

[v1.0.0]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.0.0

[Unreleased]: https://github.com/cycodehq/vscode-extension/compare/v1.13.1...HEAD
[Unreleased]: https://github.com/cycodehq/vscode-extension/compare/v1.14.0...HEAD
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "cycode",
"displayName": "Cycode",
"version": "1.13.1",
"version": "1.14.0",
"publisher": "cycode",
"description": "Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.",
"repository": {
Expand Down
1 change: 1 addition & 0 deletions src/cli/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export enum CliCommands {
export enum CommandParameters {
OutputFormatJson = '--output=json',
ByRule = '--by-rule',
ByCve = '--by-cve',
ByValue = '--by-value',
ByPath = '--by-path',
UserAgent = '--user-agent',
Expand Down
1 change: 1 addition & 0 deletions src/cli/models/cli-ignore-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export enum CliIgnoreType {
Value,
Path,
Rule,
Cve,
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export class ScaDetectionDetailsAlert {
description: string;
vulnerableRequirements?: string;
firstPatchedVersion?: string;
cveIdentifier?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class SecretDetectionDetails extends ScanDetectionDetailsBase {
customRemediationGuidelines?: string;
policyDisplayName?: string;
@Exclude({ toPlainOnly: true })
detectedValue?: string | null; // this field is used and exist only in IDE
detectedValue?: string; // this field is used and exist only in IDE

public getFilepath(): string {
return `${this.filePath}${this.fileName}`;
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const getScanTypeDisplayName = (scanType: string): string => {
return _SCAN_TYPE_TO_DISPLAY_NAME[scanType];
};

export const REQUIRED_CLI_VERSION = '2.1.0';
export const REQUIRED_CLI_VERSION = '2.2.0';

export const CLI_GITHUB = {
OWNER: 'cycodehq',
Expand Down
4 changes: 2 additions & 2 deletions src/services/cli-download-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export class CliDownloadService implements ICliDownloadService {

async getExecutableAsset(): Promise<GitHubReleaseAsset | undefined> {
const releaseInfo = await this.getGitHubLatestRelease();
if (releaseInfo == undefined) {
if (releaseInfo?.assets == undefined) {
this.logger.warn('Failed to get latest release info');
return undefined;
}
Expand Down Expand Up @@ -304,7 +304,7 @@ export class CliDownloadService implements ICliDownloadService {

async getRemoteChecksumFile(forceRefresh = false): Promise<string | undefined> {
const releaseInfo = await this.getGitHubLatestRelease(forceRefresh);
if (releaseInfo == undefined) {
if (releaseInfo?.assets == undefined) {
this.logger.warn('Failed to get latest release info');
return undefined;
}
Expand Down
2 changes: 2 additions & 0 deletions src/services/cli-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ export class CliService implements ICliService {
return CommandParameters.ByPath;
case CliIgnoreType.Path:
return CommandParameters.ByRule;
case CliIgnoreType.Cve:
return CommandParameters.ByCve;
default:
throw new Error('Invalid CliIgnoreType');
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/cycode-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class CycodeService implements ICycodeService {
} catch (error: unknown) {
captureException(error);
if (error instanceof Error) {
this.logger.error(`Error during progress: ${error.message}`);
this.logger.error(`Error during progress: ${error.message}. FN: ${fn}`);
vscode.window.showErrorMessage(`Cycode error: ${error.message}`);
}
} finally {
Expand Down
4 changes: 4 additions & 0 deletions src/ui/panels/violation/card/sca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,9 @@ export default `
<div class="section-header">Cycode Guidelines</div>
<div class="cycode-guidelines-text">None</div>
</section>
<section class="hr section-footer">
<button class="ignore-btn">Ignore this violation</button>
</section>
</section>
`;
12 changes: 11 additions & 1 deletion src/ui/panels/violation/renderer/sca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ const _resetDomState = () => {
hideElement('cycode-guidelines');
ge('cycode-guidelines-text').innerText = 'None';
hideElement('ignore-btn');
};
const renderDetection = detection => {
_resetDomState();
ge('ignore-btn').onclick = () => {
vscode.postMessage({ command: 'ignoreScaByCve', uniqueDetectionId });
};
ge('severity-icon').src = severityIcons[detection.severity];
ge('package').innerText = detection.detectionDetails.packageName;
ge('version').innerText = detection.detectionDetails.packageVersion;
Expand All @@ -28,7 +34,11 @@ const renderDetection = detection => {
if (detection.detectionDetails.alert) {
// if package vulnerability
ge('title').innerText = detection.detectionDetails.alert.summary;
if (detection.detectionDetails.alert.cveIdentifier) {
showElement('ignore-btn');
}
const cwe = renderCweCveLink(detection.detectionDetails.vulnerabilityId);
const severity = detection.severity;
ge('short-details').innerHTML = severity + ' | ' + cwe;
Expand Down
59 changes: 40 additions & 19 deletions src/ui/panels/violation/violation-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CliIgnoreType } from '../../../cli/models/cli-ignore-type';
import { CliScanType } from '../../../cli/models/cli-scan-type';
import { ILoggerService } from '../../../services/logger-service';
import { ICycodeService } from '../../../services/cycode-service';
import { ScaDetection } from '../../../cli/models/scan-result/sca/sca-detection';

const _SEVERITY_NAMES: readonly string[] = ['Critical', 'High', 'Medium', 'Low', 'Info'];

Expand Down Expand Up @@ -61,9 +62,29 @@ const _sendDetectionToRender = async (scanType: CliScanType, detection: Detectio
}
};

interface _CommandMappingAction {
scanType: CliScanType;
ignoreType: CliIgnoreType;
getIgnoreValue: (detection: DetectionBase) => string | undefined;
}

const _ignoreCommandMapping: Record<string, _CommandMappingAction> = {
ignoreSecretByValue: {
scanType: CliScanType.Secret,
ignoreType: CliIgnoreType.Value,
getIgnoreValue: (detection: DetectionBase) => (detection as SecretDetection).detectionDetails.detectedValue,
},
ignoreScaByCve: {
scanType: CliScanType.Sca,
ignoreType: CliIgnoreType.Cve,
getIgnoreValue: (detection: DetectionBase) => (detection as ScaDetection).detectionDetails.alert?.cveIdentifier,
},
};

const _ignoreCommandHandler = async (message: Record<string, string>) => {
if (message.command !== 'ignoreSecretByValue' || !message.uniqueDetectionId) {
// TODO(MarshalX): implement other ignore commands
const logger = container.resolve<ILoggerService>(LoggerServiceSymbol);
if (!message.uniqueDetectionId) {
logger.error('Unique detection id is missing in ignore command');
return;
}

Expand All @@ -73,13 +94,15 @@ const _ignoreCommandHandler = async (message: Record<string, string>) => {
return;
}

removePanel(CliScanType.Secret);
const commandInfo = _ignoreCommandMapping[message.command];
if (!commandInfo) {
logger.error('Unknown ignore command');
return;
}

removePanel(commandInfo.scanType);
await vscode.commands.executeCommand(
VscodeCommands.IgnoreCommandId,
CliScanType.Secret,
CliIgnoreType.Value,
(detection as SecretDetection).detectionDetails.detectedValue,
VscodeCommands.IgnoreCommandId, commandInfo.scanType, commandInfo.ignoreType, commandInfo.getIgnoreValue(detection),
);
};

Expand Down Expand Up @@ -150,18 +173,16 @@ const _getAiRemediationHandler = async (panel: vscode.WebviewPanel, uniqueDetect

const _getOnDidReceiveMessage = (panel: vscode.WebviewPanel, onLoadResolve: (value: boolean) => void) => {
return async (message: Record<string, string>) => {
switch (message.command) {
case 'ready':
_readyCommandHandler(onLoadResolve);
break;
case 'ignoreSecretByValue':
await _ignoreCommandHandler(message);
break;
case 'getAiRemediation':
await _getAiRemediationHandler(panel, message.uniqueDetectionId);
break;
default:
break;
if (!message.command) {
return;
}

if (message.command == 'getAiRemediation') {
await _getAiRemediationHandler(panel, message.uniqueDetectionId);
} else if (message.command == 'ready') {
_readyCommandHandler(onLoadResolve);
} else if (message.command.startsWith('ignore')) {
await _ignoreCommandHandler(message);
}
};
};
Expand Down

0 comments on commit 2d227be

Please sign in to comment.