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
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
node_modules
# don't lint build output
dist
out
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module.exports = {
'format': ['camelCase', 'UPPER_CASE', 'PascalCase'],
},
],
'@typescript-eslint/restrict-plus-operands': 'error',
// FIXME(MarshalX): refactor code and enable these rules:
'no-unused-vars': 0,
'camelcase': 0,
Expand All @@ -49,7 +50,6 @@ module.exports = {
'@typescript-eslint/no-unsafe-return': 0,
'@typescript-eslint/no-unsafe-argument': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/restrict-plus-operands': 0,
'@typescript-eslint/restrict-template-expressions': 0,
'@typescript-eslint/no-unsafe-call': 0,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Lint, test and build
name: Lint and build

on: [ push ]

Expand Down Expand Up @@ -33,21 +33,15 @@ jobs:
- name: Code Linting
run: npm run lint

- name: Run tests
run: |
sudo apt-get install xvfb
export DISPLAY=:99.0
Xvfb -ac :99 -screen 0 1920x1080x16 &
npm run test

- name: Build extension
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: |
npm install -g @vscode/vsce
vsce package
mv *.vsix cycode-extension.vsix
- name: Upload extension package

- name: Upload extension package to artifacts
uses: actions/upload-artifact@v3
with:
name: cycode-extension.vsix
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.MD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2023 Cycode Ltd.
Copyright (c) 2024 Cycode Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
18 changes: 8 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@
"type": "webview",
"id": "cycode.view.main",
"name": "scan",
"when": "cycode:auth.isAuthed && (!cycode:scan.hasDetections || !cycode:treeView.isShowed)"
"when": "cycode:auth.isAuthed && (!cycode:scan.hasAnyDetections || !cycode:treeView.isShowed)"
},
{
"type": "tree",
"id": "cycode.view.tree",
"name": "Scan Results",
"when": "cycode:scan.hasDetections && cycode:treeView.isShowed"
"when": "cycode:scan.hasAnyDetections && cycode:treeView.isShowed"
}
]
},
Expand All @@ -241,15 +241,11 @@
}
},
"scripts": {
"vscode:prepublish": "yarn run package",
"compile": "webpack",
"lint": "eslint src --ext ts",
"watch": "webpack --watch",
"compile": "webpack",
"package": "webpack --mode production",
"compile-tests": "tsc -p . --outDir out",
"watch-tests": "tsc -p . -w --outDir out",
"pretest": "yarn run compile-tests && yarn run compile && yarn run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
"vscode:prepublish": "yarn run package"
},
"devDependencies": {
"@sentry/webpack-plugin": "^2.21.1",
Expand All @@ -276,8 +272,10 @@
"dependencies": {
"@sentry/node": "^8.20.0",
"decompress": "^4.2.1",
"reflect-metadata": "^0.2.2",
"semver": "7.5.4",
"shelljs": "0.8.5",
"showdown": "^2.1.0"
"showdown": "^2.1.0",
"tsyringe": "^4.8.0"
}
}
17 changes: 10 additions & 7 deletions src/cli-wrapper/runner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {spawn} from 'child_process';
import * as os from 'os';
import {extensionOutput} from '../logging/extension-output';
import {CommandResult, RunCliArgs, RunCliResult} from './types';
import {container} from 'tsyringe';
import {ILoggerService} from '../services/logger-service';
import {LoggerServiceSymbol} from '../symbols';

const parseResult = (out: string): object => {
let result = {};
Expand All @@ -17,6 +19,7 @@ const parseResult = (out: string): object => {
};

export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {
const logger = container.resolve<ILoggerService>(LoggerServiceSymbol);
const {
cliPath,
cliEnv,
Expand All @@ -25,7 +28,7 @@ export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {
printToOutput,
} = args;

extensionOutput.info(
logger.debug(
`Running command: "${cliPath} ${commandParams.join(' ')}"`
);

Expand All @@ -39,7 +42,7 @@ export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {
});

const getCancelPromise = () => new Promise<void>((resolve) => {
extensionOutput.info(
logger.debug(
`Killing child process: "${cliPath} ${commandParams.join(' ')}"`
);

Expand All @@ -58,7 +61,7 @@ export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {
}
stderr += data.toString();
if (printToOutput) {
extensionOutput.debug(data.toString());
logger.debug(data.toString());
}
};

Expand All @@ -67,13 +70,13 @@ export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {

childProcess.on('exit', (code: number) => {
// exit occurs earlier than close
extensionOutput.debug(`Command exited with code: ${code}`);
logger.debug(`Command exited with code: ${code}`);
exitCode = code;
});

childProcess.on('close', (code: number) => {
// we receive all "data" events before close
extensionOutput.debug(`Streams of a command have been closed with code: ${code}`);
logger.debug(`Streams of a command have been closed with code: ${code}`);
resolve({
exitCode: exitCode,
stderr: stderr,
Expand All @@ -92,7 +95,7 @@ export const getRunnableCliCommand = (args: RunCliArgs): RunCliResult => {

childProcess.stdout?.on('data', (data) => {
if (printToOutput) {
extensionOutput.info(`Command stdout: ${data.toString()}`);
logger.debug(`Command stdout: ${data.toString()}`);
}

if (!data) {
Expand Down
17 changes: 17 additions & 0 deletions src/commands/auth-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as vscode from 'vscode';
import {config, validateConfig} from '../utils/config';
import {auth} from '../services/auth';

export default () => {
if (validateConfig()) {
return;
}

const params = {
config,
workspaceFolderPath:
vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '',
};

auth(params);
};
36 changes: 36 additions & 0 deletions src/commands/iac-scan-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as vscode from 'vscode';
import TrayNotifications from '../utils/tray-notifications';
import {config, validateConfig} from '../utils/config';
import {iacScan} from '../services/scanners/iac-scanner';
import {container} from 'tsyringe';
import {IExtensionService} from '../services/extension-service';
import {ExtensionServiceSymbol} from '../symbols';

export default () => {
// scan the current open document if opened

if (!vscode.window.activeTextEditor?.document ||
vscode.window?.activeTextEditor?.document?.uri.scheme === 'output'
) {
TrayNotifications.showMustBeFocusedOnFile();

return;
}

if (validateConfig()) {
return;
}

const extension = container.resolve<IExtensionService>(ExtensionServiceSymbol);

iacScan(
{
config,
pathToScan: vscode.window.activeTextEditor.document.fileName,
workspaceFolderPath: vscode.workspace.workspaceFolders?.[0]?.uri.fsPath,
diagnosticCollection: extension.diagnosticCollection,
onDemand: true,
},
extension.treeView,
);
};
30 changes: 30 additions & 0 deletions src/commands/iac-scan-for-current-project-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as vscode from 'vscode';
import {config, validateConfig} from '../utils/config';
import {iacScan} from '../services/scanners/iac-scanner';
import {container} from 'tsyringe';
import {IExtensionService} from '../services/extension-service';
import {ExtensionServiceSymbol} from '../symbols';

export default () => {
if (validateConfig()) {
return;
}

const projectPath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
if (!projectPath) {
return;
}

const extension = container.resolve<IExtensionService>(ExtensionServiceSymbol);

iacScan(
{
config,
pathToScan: projectPath,
workspaceFolderPath: projectPath,
diagnosticCollection: extension.diagnosticCollection,
onDemand: true,
},
extension.treeView,
);
};
24 changes: 24 additions & 0 deletions src/commands/ignore-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as vscode from 'vscode';
import {IgnoreCommandConfig} from '../types/commands';
import {config, validateConfig} from '../utils/config';
import {ignore} from '../services/ignore';
import {container} from 'tsyringe';
import {IExtensionService} from '../services/extension-service';
import {ExtensionServiceSymbol} from '../symbols';

export default async (ignoreConfig: IgnoreCommandConfig) => {
if (validateConfig()) {
return;
}

const extension = container.resolve<IExtensionService>(ExtensionServiceSymbol);

await ignore({
config,
workspaceFolderPath: vscode.workspace.workspaceFolders?.[0]?.uri.fsPath,
ignoreConfig,
diagnosticCollection: extension.diagnosticCollection,
treeView: extension.treeView,
});
};

69 changes: 69 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as vscode from 'vscode';
import authCommand from './auth-command';
import ignoreCommand from './ignore-command';
import scaScanCommand from './sca-scan-command';
import secretScanCommand from './secret-scan-command';
import secretScanForCurrentProjectCommand from './secret-scan-for-current-project-command';
import iacScanCommand from './iac-scan-command';
import iacScanForCurrentProjectCommand from './iac-scan-for-current-project-command';
import sastScanCommand from './sast-scan-command';
import sastScanForCurrentProjectCommand from './sast-scan-for-current-project-command';
import onTreeItemClickCommand from './on-tree-item-click-command';
import onOpenViolationInFileFromTreeItemContextMenuCommand
from './on-open-violation-in-file-from-tree-item-context-menu-command';
import onOpenViolationPanelFromTreeItemContextMenuCommand
from './on-open-violation-panel-from-tree-item-context-menu-command';
import openViolationInFileCommand from './open-violation-in-file-command';
import openViolationPanelCommand from './open-violation-panel-command';
import openSettingsCommand from './open-settings-command';
import openMainMenuCommand from './open-main-menu-command';

export enum VscodeCommands {
SecretScanCommandId = 'cycode.secretScan',
SecretScanForProjectCommandId = 'cycode.secretScanForProject',
ScaScanCommandId = 'cycode.scaScan',
IacScanCommandId = 'cycode.iacScan',
IacScanForProjectCommandId = 'cycode.iacScanForProject',
SastScanCommandId = 'cycode.sastScan',
SastScanForProjectCommandId = 'cycode.sastScanForProject',

AuthCommandId = 'cycode.auth',
IgnoreCommandId = 'cycode.ignore',

OpenSettingsCommandId = 'cycode.openSettings',
OpenMainMenuCommandId = 'cycode.openMainMenu',

ShowProblemsTab = 'workbench.action.problems.focus',
ShowCycodeView = 'workbench.view.extension.cycode',

OpenViolationInFile = 'cycode.openViolationInFile',
OpenViolationPanel = 'cycode.openViolationPanel',
OnTreeItemClick = 'cycode.onTreeItemClick',
OpenViolationInFileFromTreeItemContextMenu = 'cycode.openViolationInFileFromTreeItemContextMenu',
OpenViolationPanelFromTreeItemContextMenu = 'cycode.openViolationPanelFromTreeItemContextMenu',
}

const _VS_CODE_COMMANDS_ID_TO_CALLBACK: Record<string, (...args: any[]) => any> = {
[VscodeCommands.AuthCommandId]: authCommand,
[VscodeCommands.IgnoreCommandId]: ignoreCommand,
[VscodeCommands.SecretScanCommandId]: secretScanCommand,
[VscodeCommands.SecretScanForProjectCommandId]: secretScanForCurrentProjectCommand,
[VscodeCommands.ScaScanCommandId]: scaScanCommand,
[VscodeCommands.IacScanCommandId]: iacScanCommand,
[VscodeCommands.IacScanForProjectCommandId]: iacScanForCurrentProjectCommand,
[VscodeCommands.SastScanCommandId]: sastScanCommand,
[VscodeCommands.SastScanForProjectCommandId]: sastScanForCurrentProjectCommand,
[VscodeCommands.OnTreeItemClick]: onTreeItemClickCommand,
[VscodeCommands.OpenViolationInFileFromTreeItemContextMenu]: onOpenViolationInFileFromTreeItemContextMenuCommand,
[VscodeCommands.OpenViolationPanelFromTreeItemContextMenu]: onOpenViolationPanelFromTreeItemContextMenuCommand,
[VscodeCommands.OpenViolationInFile]: openViolationInFileCommand,
[VscodeCommands.OpenViolationPanel]: openViolationPanelCommand,
[VscodeCommands.OpenSettingsCommandId]: openSettingsCommand,
[VscodeCommands.OpenMainMenuCommandId]: openMainMenuCommand,
};

export const registerCommands = (context: vscode.ExtensionContext): void => {
for (const [commandId, commandCallback] of Object.entries(_VS_CODE_COMMANDS_ID_TO_CALLBACK)) {
context.subscriptions.push(vscode.commands.registerCommand(commandId, commandCallback));
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as vscode from 'vscode';
import {VscodeCommands} from './index';
import {TreeItem} from '../providers/tree-data/item';

export default (item: TreeItem) => {
vscode.commands.executeCommand(
VscodeCommands.OpenViolationInFile,
item.fullFilePath,
item.vulnerability?.lineNumber
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as vscode from 'vscode';
import {VscodeCommands} from './index';
import {TreeItem} from '../providers/tree-data/item';

export default (item: TreeItem) => {
vscode.commands.executeCommand(
VscodeCommands.OpenViolationPanel,
item.vulnerability?.detectionType,
item.vulnerability?.detection)
;
};
8 changes: 8 additions & 0 deletions src/commands/on-tree-item-click-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as vscode from 'vscode';
import {VscodeCommands} from './index';
import {TreeDisplayedData} from '../providers/tree-data/types';

export default async (fullFilePath: string, violation: TreeDisplayedData) => {
await vscode.commands.executeCommand(VscodeCommands.OpenViolationInFile, fullFilePath, violation.lineNumber);
vscode.commands.executeCommand(VscodeCommands.OpenViolationPanel, violation.detectionType, violation.detection);
};
Loading
Loading