Skip to content

Commit 2d227be

Browse files
authored
CM-43066 - Add the "Ignore this violation" button for violation card of SCA (#122)
1 parent 77950fa commit 2d227be

13 files changed

+74
-27
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [Unreleased]
44

5+
## [v1.14.0]
6+
7+
- Add the "Ignore this violation" button for violation card of SCA
8+
- Add support of `.gitignore` files for a file excluding from scans
9+
510
## [v1.13.1]
611

712
- Improve suggested AI fix rendering in violation cards
@@ -130,6 +135,8 @@
130135

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

138+
[v1.14.0]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.14.0
139+
133140
[v1.13.1]: https://github.com/cycodehq/vscode-extension/releases/tag/v1.13.1
134141

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

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

181-
[Unreleased]: https://github.com/cycodehq/vscode-extension/compare/v1.13.1...HEAD
188+
[Unreleased]: https://github.com/cycodehq/vscode-extension/compare/v1.14.0...HEAD

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cycode",
33
"displayName": "Cycode",
4-
"version": "1.13.1",
4+
"version": "1.14.0",
55
"publisher": "cycode",
66
"description": "Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.",
77
"repository": {

src/cli/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export enum CliCommands {
1212
export enum CommandParameters {
1313
OutputFormatJson = '--output=json',
1414
ByRule = '--by-rule',
15+
ByCve = '--by-cve',
1516
ByValue = '--by-value',
1617
ByPath = '--by-path',
1718
UserAgent = '--user-agent',

src/cli/models/cli-ignore-type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export enum CliIgnoreType {
22
Value,
33
Path,
44
Rule,
5+
Cve,
56
}

src/cli/models/scan-result/sca/sca-detection-details-alert.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ export class ScaDetectionDetailsAlert {
44
description: string;
55
vulnerableRequirements?: string;
66
firstPatchedVersion?: string;
7+
cveIdentifier?: string;
78
}

src/cli/models/scan-result/secret/secret-detection-details.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export class SecretDetectionDetails extends ScanDetectionDetailsBase {
1717
customRemediationGuidelines?: string;
1818
policyDisplayName?: string;
1919
@Exclude({ toPlainOnly: true })
20-
detectedValue?: string | null; // this field is used and exist only in IDE
20+
detectedValue?: string; // this field is used and exist only in IDE
2121

2222
public getFilepath(): string {
2323
return `${this.filePath}${this.fileName}`;

src/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export const getScanTypeDisplayName = (scanType: string): string => {
128128
return _SCAN_TYPE_TO_DISPLAY_NAME[scanType];
129129
};
130130

131-
export const REQUIRED_CLI_VERSION = '2.1.0';
131+
export const REQUIRED_CLI_VERSION = '2.2.0';
132132

133133
export const CLI_GITHUB = {
134134
OWNER: 'cycodehq',

src/services/cli-download-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ export class CliDownloadService implements ICliDownloadService {
237237

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

305305
async getRemoteChecksumFile(forceRefresh = false): Promise<string | undefined> {
306306
const releaseInfo = await this.getGitHubLatestRelease(forceRefresh);
307-
if (releaseInfo == undefined) {
307+
if (releaseInfo?.assets == undefined) {
308308
this.logger.warn('Failed to get latest release info');
309309
return undefined;
310310
}

src/services/cli-service.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ export class CliService implements ICliService {
185185
return CommandParameters.ByPath;
186186
case CliIgnoreType.Path:
187187
return CommandParameters.ByRule;
188+
case CliIgnoreType.Cve:
189+
return CommandParameters.ByCve;
188190
default:
189191
throw new Error('Invalid CliIgnoreType');
190192
}

src/services/cycode-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export class CycodeService implements ICycodeService {
5454
} catch (error: unknown) {
5555
captureException(error);
5656
if (error instanceof Error) {
57-
this.logger.error(`Error during progress: ${error.message}`);
57+
this.logger.error(`Error during progress: ${error.message}. FN: ${fn}`);
5858
vscode.window.showErrorMessage(`Cycode error: ${error.message}`);
5959
}
6060
} finally {

src/ui/panels/violation/card/sca.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,9 @@ export default `
5151
<div class="section-header">Cycode Guidelines</div>
5252
<div class="cycode-guidelines-text">None</div>
5353
</section>
54+
55+
<section class="hr section-footer">
56+
<button class="ignore-btn">Ignore this violation</button>
57+
</section>
5458
</section>
5559
`;

src/ui/panels/violation/renderer/sca.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,17 @@ const _resetDomState = () => {
1515
1616
hideElement('cycode-guidelines');
1717
ge('cycode-guidelines-text').innerText = 'None';
18+
19+
hideElement('ignore-btn');
1820
};
1921
2022
const renderDetection = detection => {
2123
_resetDomState();
2224
25+
ge('ignore-btn').onclick = () => {
26+
vscode.postMessage({ command: 'ignoreScaByCve', uniqueDetectionId });
27+
};
28+
2329
ge('severity-icon').src = severityIcons[detection.severity];
2430
ge('package').innerText = detection.detectionDetails.packageName;
2531
ge('version').innerText = detection.detectionDetails.packageVersion;
@@ -28,7 +34,11 @@ const renderDetection = detection => {
2834
if (detection.detectionDetails.alert) {
2935
// if package vulnerability
3036
ge('title').innerText = detection.detectionDetails.alert.summary;
31-
37+
38+
if (detection.detectionDetails.alert.cveIdentifier) {
39+
showElement('ignore-btn');
40+
}
41+
3242
const cwe = renderCweCveLink(detection.detectionDetails.vulnerabilityId);
3343
const severity = detection.severity;
3444
ge('short-details').innerHTML = severity + ' | ' + cwe;

src/ui/panels/violation/violation-panel.ts

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { CliIgnoreType } from '../../../cli/models/cli-ignore-type';
1212
import { CliScanType } from '../../../cli/models/cli-scan-type';
1313
import { ILoggerService } from '../../../services/logger-service';
1414
import { ICycodeService } from '../../../services/cycode-service';
15+
import { ScaDetection } from '../../../cli/models/scan-result/sca/sca-detection';
1516

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

@@ -61,9 +62,29 @@ const _sendDetectionToRender = async (scanType: CliScanType, detection: Detectio
6162
}
6263
};
6364

65+
interface _CommandMappingAction {
66+
scanType: CliScanType;
67+
ignoreType: CliIgnoreType;
68+
getIgnoreValue: (detection: DetectionBase) => string | undefined;
69+
}
70+
71+
const _ignoreCommandMapping: Record<string, _CommandMappingAction> = {
72+
ignoreSecretByValue: {
73+
scanType: CliScanType.Secret,
74+
ignoreType: CliIgnoreType.Value,
75+
getIgnoreValue: (detection: DetectionBase) => (detection as SecretDetection).detectionDetails.detectedValue,
76+
},
77+
ignoreScaByCve: {
78+
scanType: CliScanType.Sca,
79+
ignoreType: CliIgnoreType.Cve,
80+
getIgnoreValue: (detection: DetectionBase) => (detection as ScaDetection).detectionDetails.alert?.cveIdentifier,
81+
},
82+
};
83+
6484
const _ignoreCommandHandler = async (message: Record<string, string>) => {
65-
if (message.command !== 'ignoreSecretByValue' || !message.uniqueDetectionId) {
66-
// TODO(MarshalX): implement other ignore commands
85+
const logger = container.resolve<ILoggerService>(LoggerServiceSymbol);
86+
if (!message.uniqueDetectionId) {
87+
logger.error('Unique detection id is missing in ignore command');
6788
return;
6889
}
6990

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

76-
removePanel(CliScanType.Secret);
97+
const commandInfo = _ignoreCommandMapping[message.command];
98+
if (!commandInfo) {
99+
logger.error('Unknown ignore command');
100+
return;
101+
}
77102

103+
removePanel(commandInfo.scanType);
78104
await vscode.commands.executeCommand(
79-
VscodeCommands.IgnoreCommandId,
80-
CliScanType.Secret,
81-
CliIgnoreType.Value,
82-
(detection as SecretDetection).detectionDetails.detectedValue,
105+
VscodeCommands.IgnoreCommandId, commandInfo.scanType, commandInfo.ignoreType, commandInfo.getIgnoreValue(detection),
83106
);
84107
};
85108

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

151174
const _getOnDidReceiveMessage = (panel: vscode.WebviewPanel, onLoadResolve: (value: boolean) => void) => {
152175
return async (message: Record<string, string>) => {
153-
switch (message.command) {
154-
case 'ready':
155-
_readyCommandHandler(onLoadResolve);
156-
break;
157-
case 'ignoreSecretByValue':
158-
await _ignoreCommandHandler(message);
159-
break;
160-
case 'getAiRemediation':
161-
await _getAiRemediationHandler(panel, message.uniqueDetectionId);
162-
break;
163-
default:
164-
break;
176+
if (!message.command) {
177+
return;
178+
}
179+
180+
if (message.command == 'getAiRemediation') {
181+
await _getAiRemediationHandler(panel, message.uniqueDetectionId);
182+
} else if (message.command == 'ready') {
183+
_readyCommandHandler(onLoadResolve);
184+
} else if (message.command.startsWith('ignore')) {
185+
await _ignoreCommandHandler(message);
165186
}
166187
};
167188
};

0 commit comments

Comments
 (0)