From e51752d9f5f63d03da64a6ba738d4153dc14618b Mon Sep 17 00:00:00 2001 From: Dennis Tuan Anh Quach <83472928+Dboy0ZDev@users.noreply.github.com> Date: Wed, 8 Jul 2026 17:49:25 +0200 Subject: [PATCH 1/2] Implemented generateVEX command --- package.json | 4 +++ src/commands.ts | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/package.json b/package.json index ecbc792..2571f97 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,10 @@ { "command": "devguard.removeGitHooks", "title": "DevGuard: Removes Pre-Commit-Hooks for git that were previously setup by DevGuard" + }, + { + "command": "devguard.generateVEX", + "title": "DevGuard: Generate VEX (Run devguard-scanner SCA)" } ], "configuration": { diff --git a/src/commands.ts b/src/commands.ts index 140fa4b..a3b6263 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -22,6 +22,7 @@ import { //postCommitHooksExists, } from "./commitHooks"; import { StatusBarCommitHooks } from "./ui/statusBarCommitHooks"; +import os from "os"; export interface CommandDeps { client: DevGuardClient; @@ -57,6 +58,9 @@ export function registerCommands(deps: CommandDeps): vscode.Disposable[] { vscode.commands.registerCommand("devguard.removeGitHooks", () => { removeGitHooks(deps); }), + vscode.commands.registerCommand("devguard.generateVEX", () => { + generateVEX(deps); + }), ]; } @@ -524,3 +528,91 @@ function reportError(action: string, err: unknown, logger: Logger): void { `DevGuard: failed to ${action} (see DevGuard output).`, ); } + +async function generateVEX({ + logger, + sbomProvider, +}: CommandDeps): Promise { + const repoPath = + vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? process.cwd(); + const outputName = `.devguard-vex-${crypto.randomUUID()}`; + + // Token is passed via DEVGUARD_TOKEN env (not argv) so it does not appear in the process list. + const args = [ + "run", + "--rm", + "-v", + `${repoPath}:/repo`, + "-v", + `${os.tmpdir()}:${"/tmp"}`, + "ghcr.io/l3montree-dev/devguard/scanner:main", + "devguard-scanner", + "sca", + "--path=/repo", + "--output", + "cyclonedx", + ]; + + logger.info(`Running SCA scan to generate VEX …`); + + let output = ""; + const capture = (chunk: Buffer): void => { + const text = chunk.toString(); + output = text.slice(-8000); + }; + + const exitCode = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + title: `DevGuard: Generating VEX …`, + cancellable: true, + }, + (_progress, cancelToken) => + new Promise((resolve) => { + let child: ReturnType | undefined; + try { + child = spawn("docker", args); + } catch (err) { + logger.error("could not start the scanner", err); + resolve(undefined); + return; + } + cancelToken.onCancellationRequested(() => child?.kill()); + child.stdout?.on("data", capture); + child.stderr?.on("data", capture); + child.on("error", (err) => { + logger.error("scanner process error", err); + resolve(undefined); + }); + child.on("close", (code) => resolve(code ?? undefined)); + }), + ); + + if (exitCode === undefined) { + vscode.window.showErrorMessage( + `DevGuard: could not run SCA scan. Install the devguard-scanner CLI or set devguard.scannerPath.`, + ); + return; + } + if (exitCode === 0) { + let cdxjson = output; + try { + cdxjson = JSON.stringify(JSON.parse(output), null, 2); + } catch {} + await sbomProvider.open(outputName, cdxjson); + const successMessage = "DevGuard: SCA complete — VEX generated ."; + logger.info(successMessage); + vscode.window.showInformationMessage(successMessage); + return; + } + // Since we use the normal sca scan, this error check applies here as well as for generateSBOM() + if (/invalid specification version|not a valid CycloneDX/i.test(output)) { + vscode.window.showErrorMessage( + "DevGuard: the generated VEX used a CycloneDX version the scanner could not read. Rebuild devguard-scanner from source (go install ./cmd/devguard-scanner) or align your trivy version, then retry.", + ); + return; + } + vscode.window.showWarningMessage( + `DevGuard: scanner exited with code ${exitCode} (see the DevGuard output). Insights refreshed.`, + ); +} From 51650a710a41995268c294c6ce5eebe69d843104 Mon Sep 17 00:00:00 2001 From: Dennis Tuan Anh Quach <83472928+Dboy0ZDev@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:20:42 +0200 Subject: [PATCH 2/2] Fixed using wrong function for setup --- src/commands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands.ts b/src/commands.ts index a3b6263..bf24f4d 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -449,7 +449,7 @@ async function setupGitHooks({ commitHookStatusBar, }: CommandDeps): Promise { try { - await removeExistingGitHooks(); + await setupGitCommitHooks(selection); if ( await preCommitHooksExists() /* && (await postCommitHooksExists()) */ ) {