[vscode-go] src/goVulncheck: VulncheckResultViewProvider

35 views
Skip to first unread message

Hyang-Ah Hana Kim (Gerrit)

unread,
May 16, 2022, 5:03:26 PM5/16/22
to goph...@pubsubhelper.golang.org, Hyang-Ah Hana Kim, golang-co...@googlegroups.com

Hyang-Ah Hana Kim has uploaded this change for review.

View Change

src/goVulncheck: VulncheckResultViewProvider

VulncheckResultViewProvider provides a custom text document editor
to process `gopls vulncheck` JSON output and render it in a Webview.
The webview presents the data in a similar way `govulncheck -html`
presents the summary of the findings. But by implementing it inside
the extension, we can make the extension handle commands and document
links inside the editor. For example, in this CL, we embed a js script
that listens 'click' event on all links in the HTML document, and
delegates the extension part to handle link opening events. That way,
if the resource is a file type, the extension can open it inside the
editor.

For communication between the Extension side and the WebView side,
we use vscode's API to pass messages and follow the instruction in
https://code.visualstudio.com/api/extension-guides/webview#scripts-and-message-passing

The extension sends 'update' msg to the webview: that triggers update
of DOM contents based on the input.

The webview sends 'link' msg to the webview: that triggers handling
of the link opening event. All file links in the callgraph entries
carry the position information as a query parameter. The extension
parses the uri, open the file with vscode.openWith command (that allows
us to control which view column the editor should be placed, and which
line in the file should get focus).

In order to support testing, the extension and the webview exchange
'snapshot-request' and 'snapshot-result' messages. When we have UI testing
framework established, these message may be able to be replaced with it.

Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
---
A media/reset.css
A media/vscode.css
A media/vulncheckView.css
A media/vulncheckView.js
M src/goVulncheck.ts
A test/gopls/vulncheck.test.ts
A test/testdata/vuln/test.vulncheck.json
7 files changed, 587 insertions(+), 0 deletions(-)

diff --git a/media/reset.css b/media/reset.css
new file mode 100644
index 0000000..908d944
--- /dev/null
+++ b/media/reset.css
@@ -0,0 +1,25 @@
+html {
+ box-sizing: border-box;
+ font-size: 13px;
+}
+
+*,
+*:before,
+*:after {
+ box-sizing: inherit;
+}
+
+body,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+ol,
+ul {
+ margin: 0;
+ padding: 0;
+ font-weight: normal;
+}
\ No newline at end of file
diff --git a/media/vscode.css b/media/vscode.css
new file mode 100644
index 0000000..84a92ee
--- /dev/null
+++ b/media/vscode.css
@@ -0,0 +1,40 @@
+:root {
+ --container-paddding: 20px;
+ --input-padding-vertical: 6px;
+ --input-padding-horizontal: 4px;
+ --input-margin-vertical: 4px;
+ --input-margin-horizontal: 0;
+}
+
+body {
+ padding: 0 var(--container-paddding);
+ color: var(--vscode-foreground);
+ font-size: var(--vscode-font-size);
+ font-weight: var(--vscode-font-weight);
+ font-family: var(--vscode-font-family);
+ background-color: var(--vscode-editor-background);
+}
+
+body > *,
+form > * {
+ margin-block-start: var(--input-margin-vertical);
+ margin-block-end: var(--input-margin-vertical);
+}
+
+*:focus {
+ outline-color: var(--vscode-focusBorder) !important;
+}
+
+a {
+ color: var(--vscode-textLink-foreground);
+}
+
+a:hover,
+a:active {
+ color: var(--vscode-textLink-activeForeground);
+}
+
+code {
+ font-size: var(--vscode-editor-font-size);
+ font-family: var(--vscode-editor-font-family);
+}
\ No newline at end of file
diff --git a/media/vulncheckView.css b/media/vulncheckView.css
new file mode 100644
index 0000000..2467fcf
--- /dev/null
+++ b/media/vulncheckView.css
@@ -0,0 +1,37 @@
+.log {
+ font-weight: lighter;
+}
+
+.vuln {
+ text-align: left;
+ padding-bottom: 1em;
+}
+
+.vuln-desc {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+}
+
+.vuln-details {
+ padding-bottom: 0.5em;
+}
+
+details summary {
+ cursor: pointer;
+ position: relative;
+}
+
+details summary > * {
+ display: inline;
+ position: relative;
+}
+
+.stacks {
+ padding: 1em;
+}
+
+.stack {
+ padding: 1em;
+ font-size: var(--vscode-editor-font-size);
+ font-family: var(--vscode-editor-font-family);
+}
\ No newline at end of file
diff --git a/media/vulncheckView.js b/media/vulncheckView.js
new file mode 100644
index 0000000..0f5c29a
--- /dev/null
+++ b/media/vulncheckView.js
@@ -0,0 +1,178 @@
+/*---------------------------------------------------------
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+// Script for VulncheckResultViewProvider's webview.
+
+(function () {
+
+ // @ts-ignore
+ const vscode = acquireVsCodeApi();
+
+ const logContainer = /** @type {HTMLElement} */ (document.querySelector('.log'));
+ const vulnsContainer = /** @type {HTMLElement} */ (document.querySelector('.vulns'));
+
+ vulnsContainer.addEventListener('click', (event) => {
+ let node = event && event.target;
+ if (node && node.tagName && node.tagName === 'A' && node.href) {
+ // Ask vscode to handle link opening.
+ vscode.postMessage({ type: 'open', target: node.href });
+ event.preventDefault();
+ event.stopPropagation();
+ return;
+ }
+ });
+
+ const errorContainer = document.createElement('div');
+ document.body.appendChild(errorContainer);
+ errorContainer.className = 'error'
+ errorContainer.style.display = 'none'
+
+ function moduleVersion(/** @type {string} */mod, /** @type {string|undefined} */ver) {
+ if (ver) {
+ return `<a href="https://pkg.go.dev/${mod}@${ver}">${mod}@${ver}</a>`;
+ }
+ return 'N/A'
+ }
+
+ function snapshotContent() {
+ return vulnsContainer.innerHTML;
+ }
+
+ /**
+ * Render the document in the webview.
+ */
+ function updateContent(/** @type {string} */ text) {
+ let json;
+ try {
+ if (!text) {
+ text = '{}';
+ }
+ json = JSON.parse(text);
+ } catch {
+ errorContainer.innerText = 'Error: Document is not valid json';
+ errorContainer.style.display = '';
+ return;
+ }
+ errorContainer.style.display = 'none';
+
+ logContainer.innerHTML = '';
+ const runLog = document.createElement('table');
+ const timeinfo = (startDate, durationMillisec) => {
+ if (!startDate) { return '' }
+ return durationMillisec ? `${startDate} (took ${durationMillisec} msec)` : `${startDate}`;
+ }
+
+ runLog.innerHTML = `
+<tr><td>Dir:</td><td>${json.Dir || ''}</td></tr>
+<tr><td>Pattern:</td><td>${json.Pattern || ''}</td></tr>
+<tr><td>Analyzed at:</td><td>${timeinfo(json.Start, json.Duration)}</td></tr>`;
+ logContainer.appendChild(runLog);
+
+ const vulns = json.Vuln || [];
+ vulnsContainer.innerHTML = '';
+
+ vulns.forEach((vuln) => {
+ const element = document.createElement('div');
+ element.className = 'vuln';
+ vulnsContainer.appendChild(element);
+
+ // TITLE - Vuln ID
+ const title = document.createElement('h2');
+ title.innerHTML = `<a href="${vuln.URL}">${vuln.ID}</a>`;
+ title.className = 'vuln-title';
+ element.appendChild(title);
+
+ // DESCRIPTION - short text (alases)
+ const desc = document.createElement('p');
+ desc.innerHTML = Array.isArray(vuln.Aliases) && vuln.Aliases.length ? `${vuln.Details} (${vuln.Aliases.join(', ')})` : vuln.Details;
+ desc.className = 'vuln-desc';
+ element.appendChild(desc);
+
+ // DETAILS - dump of all details
+ const details = document.createElement('table');
+ details.className = 'vuln-details'
+ details.innerHTML = `
+ <tr><td>Package</td><td>${vuln.PkgPath}</td></tr>
+ <tr><td>Current Version</td><td>${moduleVersion(vuln.ModPath, vuln.CurrentVersion)}</td></tr>
+ <tr><td>Fixed Version</td><td>${moduleVersion(vuln.ModPath, vuln.FixedVersion)}</td></tr>
+ `;
+ element.appendChild(details);
+
+ /* TODO: Action for module version upgrade */
+ /* TODO: Explain module dependency - why am I depending on this vulnerable version? */
+
+ // EXAMPLARS - call stacks (initially hidden)
+ const examples = document.createElement('details');
+ examples.innerHTML = `<summary>${vuln.CallStackSummaries?.length || 0}+ findings</summary>`;
+
+ // Call stacks
+ const callstacksContainer = document.createElement('p');
+ callstacksContainer.className = 'stacks';
+ vuln.CallStackSummaries?.forEach((summary, idx) => {
+ const callstack = document.createElement('details');
+ const s = document.createElement('summary');
+ s.innerText = summary;
+ callstack.appendChild(s);
+
+ const stack = document.createElement('div');
+ stack.className = 'stack';
+ const cs = vuln.CallStacks[idx];
+ cs.forEach((c) => {
+ const p = document.createElement('p');
+ const pos = c.URI ? `${c.URI}?${c.Pos.line || 0}` : '';
+ p.innerHTML = pos ? `<a href="${pos}">${c.Name}</a>` : c.Name;
+ stack.appendChild(p);
+ });
+ callstack.appendChild(stack);
+
+ callstacksContainer.appendChild(callstack);
+ })
+
+ examples.appendChild(callstacksContainer);
+ element.appendChild(examples);
+ });
+ }
+
+ // Message Passing between Extension and Webview
+ //
+ // Extension sends 'update' to Webview to trigger rerendering.
+ // Webview sends 'link' to Extension to forward all link
+ // click events so the extension can handle the event.
+ //
+ // Extension sends 'snapshot-request' to trigger dumping
+ // of the current DOM in the 'vulns' container.
+ // Webview sends 'snapshot-result' to the extension
+ // as the response to snapshot-request.
+
+ // Handle messages sent from the extension to the webview
+ window.addEventListener('message', event => {
+ const message = event.data; // The json data that the extension sent
+ switch (message.type) {
+ case 'update':
+ const text = message.text;
+
+ updateContent(text);
+ // Then persist state information.
+ // This state is returned in the call to `vscode.getState` below when a webview is reloaded.
+ vscode.setState({ text });
+ return;
+ // Message for testing. Returns a current DOM in a serialized format.
+ case 'snapshot-request':
+ const result = snapshotContent();
+ vscode.postMessage({ type: 'snapshot-result', target: result });
+ return;
+ }
+ });
+
+ // Webviews are normally torn down when not visible and re-created when they become visible again.
+ // State lets us save information across these re-loads
+ const state = vscode.getState();
+ if (state) {
+ updateContent(state.text);
+ };
+ // TODO: Handle 'details' expansion info and store the state using
+ // vscode.setState or retainContextWhenHidden. Currently, we are storing only
+ // the document text. (see windowEventHandler)
+}());
diff --git a/src/goVulncheck.ts b/src/goVulncheck.ts
index 96cb6ea..9d01bfe 100644
--- a/src/goVulncheck.ts
+++ b/src/goVulncheck.ts
@@ -11,6 +11,126 @@
import { toolExecutionEnvironment } from './goEnv';
import { killProcessTree } from './utils/processUtils';
import * as readline from 'readline';
+import { URI } from 'vscode-uri';
+
+export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvider {
+ public static readonly viewType = 'vulncheck.view';
+
+ public static register({ extensionUri, subscriptions }: vscode.ExtensionContext): VulncheckResultViewProvider {
+ const provider = new VulncheckResultViewProvider(extensionUri);
+ subscriptions.push(vscode.window.registerCustomEditorProvider(VulncheckResultViewProvider.viewType, provider));
+ return provider;
+ }
+
+ constructor(private readonly extensionUri: vscode.Uri) {}
+
+ /**
+ * Called when our custom editor is opened.
+ */
+ public async resolveCustomTextEditor(
+ document: vscode.TextDocument,
+ webviewPanel: vscode.WebviewPanel,
+ _: vscode.CancellationToken // eslint-disable-line @typescript-eslint/no-unused-vars
+ ): Promise<void> {
+ // Setup initial content for the webview
+ webviewPanel.webview.options = { enableScripts: true };
+ webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview);
+
+ // Receive message from the webview.
+ webviewPanel.webview.onDidReceiveMessage(this.handleMessage);
+
+ function updateWebview() {
+ webviewPanel.webview.postMessage({ type: 'update', text: document.getText() });
+ }
+
+ // Hook up event handlers so that we can synchronize the webview with the text document.
+ //
+ // The text document acts as our model, so we have to sync change in the document to our
+ // editor and sync changes in the editor back to the document.
+ //
+ // Remember that a single text document can also be shared between multiple custom
+ // editors (this happens for example when you split a custom editor)
+ const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument((e) => {
+ if (e.document.uri.toString() === document.uri.toString()) {
+ updateWebview();
+ }
+ });
+
+ // Make sure we get rid of the listener when our editor is closed.
+ webviewPanel.onDidDispose(() => {
+ changeDocumentSubscription.dispose();
+ });
+
+ updateWebview();
+ }
+
+ /**
+ * Get the static html used for the editor webviews.
+ */
+ private getHtmlForWebview(webview: vscode.Webview): string {
+ const mediaUri = vscode.Uri.joinPath(this.extensionUri, 'media');
+ // Local path to script and css for the webview
+ const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vulncheckView.js'));
+ const styleResetUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'reset.css'));
+ const styleVSCodeUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vscode.css'));
+ const styleMainUri = webview.asWebviewUri(vscode.Uri.joinPath(mediaUri, 'vulncheckView.css'));
+
+ // Use a nonce to whitelist which scripts can be run
+ const nonce = getNonce();
+
+ return /* html */ `
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <!--
+ Use a content security policy to only allow loading images from https or from our extension directory,
+ and only allow scripts that have a specific nonce.
+ -->
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src ${webview.cspSource}; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="${styleResetUri}" rel="stylesheet" />
+ <link href="${styleVSCodeUri}" rel="stylesheet" />
+ <link href="${styleMainUri}" rel="stylesheet" />
+ <title>Vulnerability Report - govulncheck</title>
+ </head>
+ <body>
+ <div class="log"></div>
+ <div class="vulns"></div>
+
+ <script nonce="${nonce}" src="${scriptUri}"></script>
+ </body>
+ </html>`;
+ }
+
+ private handleMessage(e: { type: string; target?: string }): void {
+ switch (e.type) {
+ case 'open':
+ {
+ if (!e.target) return;
+ const uri = safeURIParse(e.target);
+ if (!uri || !uri.scheme) return;
+ if (uri.scheme === 'https') {
+ vscode.env.openExternal(uri);
+ } else if (uri.scheme === 'file') {
+ const line = uri.query ? Number(uri.query.split(':')[0]) : undefined;
+ const range = line ? new vscode.Range(line, 0, line, 0) : undefined;
+ vscode.window.showTextDocument(
+ vscode.Uri.from({ scheme: uri.scheme, path: uri.path }),
+ // prefer the first column to present the source.
+ { viewColumn: vscode.ViewColumn.One, selection: range }
+ );
+ }
+ }
+ return;
+ case 'snapshot-result':
+ // response for `snapshot-request`.
+ return;
+ default:
+ console.log(`unrecognized type message: ${e.type}`);
+ }
+ }
+}

export class VulncheckProvider {
static scheme = 'govulncheck';
@@ -256,3 +376,20 @@
character: number;
};
}
+
+function getNonce() {
+ let text = '';
+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ for (let i = 0; i < 32; i++) {
+ text += possible.charAt(Math.floor(Math.random() * possible.length));
+ }
+ return text;
+}
+
+function safeURIParse(s: string): URI | undefined {
+ try {
+ return URI.parse(s);
+ } catch (_) {
+ return undefined;
+ }
+}
diff --git a/test/gopls/vulncheck.test.ts b/test/gopls/vulncheck.test.ts
new file mode 100644
index 0000000..5e14408
--- /dev/null
+++ b/test/gopls/vulncheck.test.ts
@@ -0,0 +1,85 @@
+/*---------------------------------------------------------
+ * Copyright 2022 The Go Authors. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+import assert from 'assert';
+import path = require('path');
+import vscode = require('vscode');
+import { extensionId } from '../../src/const';
+import goVulncheck = require('../../src/goVulncheck');
+
+suite.only('vulncheck result viewer tests', () => {
+ const webviewId = 'vulncheck';
+ const extensionUri = vscode.extensions.getExtension(extensionId)!.extensionUri;
+ const fixtureDir = path.join(__dirname, '..', '..', '..', 'test', 'testdata', 'vuln');
+
+ const disposables: vscode.Disposable[] = [];
+ function _register<T extends vscode.Disposable>(disposable: T) {
+ disposables.push(disposable);
+ return disposable;
+ }
+ let provider: goVulncheck.VulncheckResultViewProvider;
+
+ setup(() => {
+ provider = new goVulncheck.VulncheckResultViewProvider(extensionUri);
+ });
+
+ teardown(async () => {
+ await vscode.commands.executeCommand('workbench.action.closeAllEditors');
+ vscode.Disposable.from(...disposables).dispose();
+ });
+
+ test('populates webview', async () => {
+ const webviewPanel = _register(
+ vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {})
+ );
+ const source = path.join(fixtureDir, 'test.vulncheck.json');
+ const doc = await vscode.workspace.openTextDocument(source);
+ const canceller = new vscode.CancellationTokenSource();
+ _register(canceller);
+
+ const watcher = getMessage<{ type: string; target?: string }>(webviewPanel);
+
+ await provider.resolveCustomTextEditor(doc, webviewPanel, canceller.token);
+ webviewPanel.reveal();
+
+ // Trigger snapshotContent that sends `snapshot-result` as a result.
+ webviewPanel.webview.postMessage({ type: 'snapshot-request' });
+ const res = await watcher;
+
+ assert.deepStrictEqual(res.type, 'snapshot-result', `want snapshot-result, got ${JSON.stringify(res)}`);
+ assert(res.target && res.target.includes('GO-2021-0113'), res.target);
+ });
+
+ test('handles invalid input', async () => {
+ const webviewPanel = _register(
+ vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {})
+ );
+ // Empty doc.
+ const doc = await vscode.workspace.openTextDocument(
+ vscode.Uri.file('bogus.vulncheck.json').with({ scheme: 'untitled' })
+ );
+ const canceller = new vscode.CancellationTokenSource();
+ _register(canceller);
+
+ const watcher = getMessage<{ type: string; target?: string }>(webviewPanel);
+
+ await provider.resolveCustomTextEditor(doc, webviewPanel, canceller.token);
+ webviewPanel.reveal();
+
+ // Trigger snapshotContent that sends `snapshot-result` as a result.
+ webviewPanel.webview.postMessage({ type: 'snapshot-request' });
+ const res = await watcher;
+ assert.deepStrictEqual(res.type, 'snapshot-result', `want snapshot-result, got ${JSON.stringify(res)}`);
+ assert(!res.target, res.target);
+ });
+});
+
+function getMessage<R = { type: string; target?: string }>(webview: vscode.WebviewPanel): Promise<R> {
+ return new Promise<R>((resolve) => {
+ const sub = webview.webview.onDidReceiveMessage((message) => {
+ sub.dispose();
+ resolve(message);
+ });
+ });
+}
diff --git a/test/testdata/vuln/test.vulncheck.json b/test/testdata/vuln/test.vulncheck.json
new file mode 100644
index 0000000..79a19ad
--- /dev/null
+++ b/test/testdata/vuln/test.vulncheck.json
@@ -0,0 +1,47 @@
+{
+ "Vuln": [
+ {
+ "ID": "GO-2021-0113",
+ "Details": "Due to improper index calculation, an incorrectly formatted language tag can cause Parse\nto panic via an out of bounds read. If Parse is used to process untrusted user inputs,\nthis may be used as a vector for a denial of service attack.\n",
+ "Aliases": [
+ "CVE-2021-38561"
+ ],
+ "Symbol": "Parse",
+ "PkgPath": "golang.org/x/text/language",
+ "ModPath": "golang.org/x/text",
+ "URL": "https://pkg.go.dev/vuln/GO-2021-0113",
+ "CurrentVersion": "v0.0.0-20170915032832-14c0d48ead0c",
+ "FixedVersion": "v0.3.7",
+ "CallStacks": [
+ [
+ {
+ "Name": "github.com/golang/vscode-go/test/testdata/vuln.main",
+ "URI": "file:///Users/hakim/projects/vscode-go/test/testdata/vuln/test.go",
+ "Pos": {
+ "line": 9,
+ "character": 0
+ }
+ },
+ {
+ "Name": "golang.org/x/text/language.Parse",
+ "URI": "file:///Users/hakim/go/pkg/mod/golang.org/x/te...@v0.0.0-20170915032832-14c0d48ead0c/language/parse.go",
+ "Pos": {
+ "line": 227,
+ "character": 0
+ }
+ }
+ ]
+ ],
+ "CallStackSummaries": [
+ "github.com/golang/vscode-go/test/testdata/vuln.main calls golang.org/x/text/language.Parse"
+ ],
+ "AffectedPkgs": [
+ "github.com/golang/vscode-go/test/testdata/vuln"
+ ]
+ }
+ ],
+ "Start": "2022-05-16T13:43:54.437Z",
+ "Duration": 1407,
+ "Dir": "/Users/hakim/projects/vscode-go/test/testdata/vuln",
+ "Pattern": "./..."
+}

To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: vscode-go
Gerrit-Branch: master
Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
Gerrit-Change-Number: 406300
Gerrit-PatchSet: 1
Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
Gerrit-MessageType: newchange

Hyang-Ah Hana Kim (Gerrit)

unread,
May 16, 2022, 6:21:34 PM5/16/22
to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

Attention is currently required from: Jamal Carvalho, Suzy Mueller.

Patch set 1:Run-TryBot +1

View Change

    To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: vscode-go
    Gerrit-Branch: master
    Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
    Gerrit-Change-Number: 406300
    Gerrit-PatchSet: 1
    Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
    Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
    Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
    Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
    Gerrit-CC: Gopher Robot <go...@golang.org>
    Gerrit-Attention: Suzy Mueller <suz...@golang.org>
    Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
    Gerrit-Comment-Date: Mon, 16 May 2022 22:21:31 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    Gerrit-MessageType: comment

    kokoro (Gerrit)

    unread,
    May 16, 2022, 6:39:42 PM5/16/22
    to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

    Attention is currently required from: Jamal Carvalho, Suzy Mueller.

    Kokoro presubmit build finished with status: SUCCESS
    Logs at: https://source.cloud.google.com/results/invocations/8027bd9d-2829-45f5-8d13-379c09a0ffb6

    Patch set 1:TryBot-Result +1

    View Change

      To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: vscode-go
      Gerrit-Branch: master
      Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
      Gerrit-Change-Number: 406300
      Gerrit-PatchSet: 1
      Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
      Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
      Gerrit-Reviewer: kokoro <noreply...@google.com>
      Gerrit-CC: Gopher Robot <go...@golang.org>
      Gerrit-Attention: Suzy Mueller <suz...@golang.org>
      Gerrit-Attention: Jamal Carvalho <ja...@golang.org>
      Gerrit-Comment-Date: Mon, 16 May 2022 22:39:39 +0000

      Jamal Carvalho (Gerrit)

      unread,
      May 17, 2022, 10:17:05 AM5/17/22
      to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, kokoro, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

      Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

      Patch set 1:Code-Review +2

      View Change

      9 comments:

      To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: vscode-go
      Gerrit-Branch: master
      Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
      Gerrit-Change-Number: 406300
      Gerrit-PatchSet: 1
      Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
      Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
      Gerrit-Reviewer: kokoro <noreply...@google.com>
      Gerrit-CC: Gopher Robot <go...@golang.org>
      Gerrit-Attention: Suzy Mueller <suz...@golang.org>
      Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Comment-Date: Tue, 17 May 2022 14:17:00 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Gerrit-MessageType: comment

      Hyang-Ah Hana Kim (Gerrit)

      unread,
      May 18, 2022, 10:54:57 AM5/18/22
      to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

      Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

      Hyang-Ah Hana Kim uploaded patch set #2 to this change.

      View Change

      The following approvals got outdated and were removed: Run-TryBot+1 by Hyang-Ah Hana Kim, TryBot-Result+1 by kokoro

      7 files changed, 599 insertions(+), 0 deletions(-)

      To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: vscode-go
      Gerrit-Branch: master
      Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
      Gerrit-Change-Number: 406300
      Gerrit-PatchSet: 2
      Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
      Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
      Gerrit-Reviewer: kokoro <noreply...@google.com>
      Gerrit-CC: Gopher Robot <go...@golang.org>
      Gerrit-Attention: Suzy Mueller <suz...@golang.org>
      Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
      Gerrit-MessageType: newpatchset

      kokoro (Gerrit)

      unread,
      May 18, 2022, 11:11:55 AM5/18/22
      to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

      Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

      Kokoro presubmit build finished with status: SUCCESS
      Logs at: https://source.cloud.google.com/results/invocations/161ae06a-69b6-4aac-b09c-e33fa75f9b78

      Patch set 2:TryBot-Result +1

      View Change

        To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: vscode-go
        Gerrit-Branch: master
        Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
        Gerrit-Change-Number: 406300
        Gerrit-PatchSet: 2
        Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
        Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
        Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
        Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
        Gerrit-Reviewer: kokoro <noreply...@google.com>
        Gerrit-CC: Gopher Robot <go...@golang.org>
        Gerrit-Attention: Suzy Mueller <suz...@golang.org>
        Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
        Gerrit-Comment-Date: Wed, 18 May 2022 15:11:50 +0000

        kokoro (Gerrit)

        unread,
        May 18, 2022, 12:14:08 PM5/18/22
        to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

        Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

        Kokoro presubmit build finished with status: FAILURE
        Logs at: https://source.cloud.google.com/results/invocations/94ebb3b1-5ba2-452b-88e7-4f767c445821

        Patch set 3:TryBot-Result -1

        View Change

          To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: vscode-go
          Gerrit-Branch: master
          Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
          Gerrit-Change-Number: 406300
          Gerrit-PatchSet: 3
          Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
          Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
          Gerrit-Reviewer: kokoro <noreply...@google.com>
          Gerrit-CC: Gopher Robot <go...@golang.org>
          Gerrit-Attention: Suzy Mueller <suz...@golang.org>
          Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-Comment-Date: Wed, 18 May 2022 16:14:03 +0000

          Hyang-Ah Hana Kim (Gerrit)

          unread,
          May 18, 2022, 3:24:15 PM5/18/22
          to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, golang-co...@googlegroups.com

          Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

          Hyang-Ah Hana Kim uploaded patch set #4 to this change.

          View Change

          The following approvals got outdated and were removed: Run-TryBot+1 by Hyang-Ah Hana Kim, TryBot-Result-1 by kokoro

          src/goVulncheck: add VulncheckResultViewProvider

          To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: vscode-go
          Gerrit-Branch: master
          Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
          Gerrit-Change-Number: 406300
          Gerrit-PatchSet: 4
          Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
          Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
          Gerrit-Reviewer: kokoro <noreply...@google.com>
          Gerrit-CC: Gopher Robot <go...@golang.org>
          Gerrit-Attention: Suzy Mueller <suz...@golang.org>
          Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
          Gerrit-MessageType: newpatchset

          kokoro (Gerrit)

          unread,
          May 18, 2022, 3:41:59 PM5/18/22
          to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

          Attention is currently required from: Hyang-Ah Hana Kim, Suzy Mueller.

          Kokoro presubmit build finished with status: SUCCESS
          Logs at: https://source.cloud.google.com/results/invocations/c434efcc-8a00-4a6a-a673-20d5fb4feccb

          Patch set 4:TryBot-Result +1

          View Change

            To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: vscode-go
            Gerrit-Branch: master
            Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
            Gerrit-Change-Number: 406300
            Gerrit-PatchSet: 4
            Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
            Gerrit-Reviewer: kokoro <noreply...@google.com>
            Gerrit-CC: Gopher Robot <go...@golang.org>
            Gerrit-Attention: Suzy Mueller <suz...@golang.org>
            Gerrit-Attention: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Comment-Date: Wed, 18 May 2022 19:41:55 +0000

            Hyang-Ah Hana Kim (Gerrit)

            unread,
            May 18, 2022, 4:10:49 PM5/18/22
            to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, kokoro, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

            Attention is currently required from: Suzy Mueller.

            View Change

            8 comments:

            • File media/vulncheckView.css:

              • Done. Ran formatter.

              • Can you use optional chaining throughout this file? e.g.,`node?.tagName === 'A' && node. […]

                oh, thanks!

              • You can remove this if you add a default parameter on 46. […]

                Indeed.

              • Done

              • Done

            • File test/gopls/vulncheck.test.ts:

              • Remove . […]

                🤦🏾‍♀️

            To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: vscode-go
            Gerrit-Branch: master
            Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
            Gerrit-Change-Number: 406300
            Gerrit-PatchSet: 4
            Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
            Gerrit-Reviewer: kokoro <noreply...@google.com>
            Gerrit-CC: Gopher Robot <go...@golang.org>
            Gerrit-Attention: Suzy Mueller <suz...@golang.org>
            Gerrit-Comment-Date: Wed, 18 May 2022 20:10:45 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            Comment-In-Reply-To: Jamal Carvalho <ja...@golang.org>
            Gerrit-MessageType: comment

            Hyang-Ah Hana Kim (Gerrit)

            unread,
            May 18, 2022, 4:40:38 PM5/18/22
            to Hyang-Ah Hana Kim, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, kokoro, Jamal Carvalho, Suzy Mueller, Gopher Robot, golang-co...@googlegroups.com

            Hyang-Ah Hana Kim submitted this change.

            View Change



            1 is the latest approved patch-set.
            The change was submitted with unreviewed changes in the following files:

            ```
            The name of the file: media/vulncheckView.css
            Insertions: 10, Deletions: 5.

            @@ -1,5 +1,10 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
             .log {
            - font-weight: lighter;
            + font-weight: lighter;
            }

            .vuln {
            @@ -16,13 +21,13 @@
            padding-bottom: 0.5em;
            }

            -details summary {
            - cursor: pointer;

            +details summary {
            + cursor: pointer;
             	position: relative;
            }

            -details summary > * {
            - display: inline;

            +details summary>* {
            + display: inline;
             	position: relative;
            }

            ```
            ```
            The name of the file: test/gopls/vulncheck.test.ts
            Insertions: 1, Deletions: 1.

            @@ -8,7 +8,7 @@
            import { extensionId } from '../../src/const';

            import goVulncheck = require('../../src/goVulncheck');

            -suite.only('vulncheck result viewer tests', () => {
            +suite('vulncheck result viewer tests', () => {
            const webviewId = 'vulncheck';
            const extensionUri = vscode.extensions.getExtension(extensionId)!.extensionUri;

            const fixtureDir = path.join(__dirname, '..', '..', '..', 'test', 'testdata', 'vuln');
            ```
            ```
            The name of the file: media/reset.css
            Insertions: 5, Deletions: 0.

            @@ -1,3 +1,8 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
             html {
            box-sizing: border-box;
            font-size: 13px;
            ```
            ```
            The name of the file: media/vulncheckView.js
            Insertions: 4, Deletions: 7.

            @@ -15,7 +15,7 @@


            vulnsContainer.addEventListener('click', (event) => {
             		let node = event && event.target;
            -		if (node && node.tagName && node.tagName === 'A' && node.href) {
            + if (node?.tagName === 'A' && node.href) {

            // Ask vscode to handle link opening.
             			vscode.postMessage({ type: 'open', target: node.href });
             			event.preventDefault();
            @@ -43,12 +43,9 @@
            /**

            * Render the document in the webview.
             	 */
            - function updateContent(/** @type {string} */ text) {
            + function updateContent(/** @type {string} */ text = '{}') {
            let json;
            try {
            - if (!text) {
            - text = '{}';
            - }
            json = JSON.parse(text);
            } catch {

            errorContainer.innerText = 'Error: Document is not valid json';
            @@ -84,7 +81,7 @@
            title.className = 'vuln-title';
            element.appendChild(title);

            - // DESCRIPTION - short text (alases)
            + // DESCRIPTION - short text (aliases)

            const desc = document.createElement('p');
             			desc.innerHTML = Array.isArray(vuln.Aliases) && vuln.Aliases.length ? `${vuln.Details} (${vuln.Aliases.join(', ')})` : vuln.Details;
             			desc.className = 'vuln-desc';
            @@ -103,7 +100,7 @@

            /* TODO: Action for module version upgrade */
             			/* TODO: Explain module dependency - why am I depending on this vulnerable version? */

            -			// EXAMPLARS - call stacks (initially hidden)
            + // EXEMPLARS - call stacks (initially hidden)

            const examples = document.createElement('details');
             			examples.innerHTML = `<summary>${vuln.CallStackSummaries?.length || 0}+ findings</summary>`;

            ```
            ```
            The name of the file: media/vscode.css
            Insertions: 7, Deletions: 2.

            @@ -1,3 +1,8 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
             :root {
            --container-paddding: 20px;
            --input-padding-vertical: 6px;
            @@ -15,8 +20,8 @@
            background-color: var(--vscode-editor-background);
            }

            -body > *,
            -form > * {
            +body>*,
            +form>* {
            margin-block-start: var(--input-margin-vertical);
            margin-block-end: var(--input-margin-vertical);
            }
            ```

            Approvals: Jamal Carvalho: Looks good to me, approved kokoro: TryBots succeeded Hyang-Ah Hana Kim: Run TryBots
            Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/406300
            TryBot-Result: kokoro <noreply...@google.com>
            Run-TryBot: Hyang-Ah Hana Kim <hya...@gmail.com>
            Reviewed-by: Jamal Carvalho <ja...@golang.org>

            ---
            A media/reset.css
            A media/vscode.css
            A media/vulncheckView.css
            A media/vulncheckView.js
            M src/goVulncheck.ts
            A test/gopls/vulncheck.test.ts
            A test/testdata/vuln/test.vulncheck.json
            7 files changed, 603 insertions(+), 0 deletions(-)

            diff --git a/media/reset.css b/media/reset.css
            new file mode 100644
            index 0000000..002b994
            --- /dev/null
            +++ b/media/reset.css
            @@ -0,0 +1,30 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
            index 0000000..b4f7c42
            --- /dev/null
            +++ b/media/vscode.css
            @@ -0,0 +1,45 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
            index 0000000..96cc78f
            --- /dev/null
            +++ b/media/vulncheckView.css
            @@ -0,0 +1,42 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
            index 0000000..6a2a4a0
            --- /dev/null
            +++ b/media/vulncheckView.js
            @@ -0,0 +1,175 @@

            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +
            +// Script for VulncheckResultViewProvider's webview.
            +
            +(function () {
            +
            + // @ts-ignore
            + const vscode = acquireVsCodeApi();
            +
            + const logContainer = /** @type {HTMLElement} */ (document.querySelector('.log'));
            + const vulnsContainer = /** @type {HTMLElement} */ (document.querySelector('.vulns'));
            +
            + vulnsContainer.addEventListener('click', (event) => {
            + let node = event && event.target;
            +		if (node?.tagName === 'A' && node.href) {
            +	function updateContent(/** @type {string} */ text = '{}') {

            + let json;
            + try {
            +			// DESCRIPTION - short text (aliases)

            + const desc = document.createElement('p');
            + desc.innerHTML = Array.isArray(vuln.Aliases) && vuln.Aliases.length ? `${vuln.Details} (${vuln.Aliases.join(', ')})` : vuln.Details;
            + desc.className = 'vuln-desc';
            + element.appendChild(desc);
            +
            + // DETAILS - dump of all details
            + const details = document.createElement('table');
            + details.className = 'vuln-details'
            + details.innerHTML = `
            + <tr><td>Package</td><td>${vuln.PkgPath}</td></tr>
            + <tr><td>Current Version</td><td>${moduleVersion(vuln.ModPath, vuln.CurrentVersion)}</td></tr>
            + <tr><td>Fixed Version</td><td>${moduleVersion(vuln.ModPath, vuln.FixedVersion)}</td></tr>
            + `;
            + element.appendChild(details);
            +
            + /* TODO: Action for module version upgrade */
            + /* TODO: Explain module dependency - why am I depending on this vulnerable version? */
            +
            +			// EXEMPLARS - call stacks (initially hidden)
            index 10de439..76e4d62 100644
            index 0000000..5f696bc

            --- /dev/null
            +++ b/test/gopls/vulncheck.test.ts
            @@ -0,0 +1,85 @@
            +/*---------------------------------------------------------
            + * Copyright 2022 The Go Authors. All rights reserved.
            + * Licensed under the MIT License. See LICENSE in the project root for license information.
            + *--------------------------------------------------------*/
            +import assert from 'assert';
            +import path = require('path');
            +import vscode = require('vscode');
            +import { extensionId } from '../../src/const';
            +import goVulncheck = require('../../src/goVulncheck');
            +
            +suite('vulncheck result viewer tests', () => {

            To view, visit change 406300. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: vscode-go
            Gerrit-Branch: master
            Gerrit-Change-Id: I9a343b972642a9197313d9d42af37b5a2d5ccefa
            Gerrit-Change-Number: 406300
            Gerrit-PatchSet: 5
            Gerrit-Owner: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Hyang-Ah Hana Kim <hya...@gmail.com>
            Gerrit-Reviewer: Jamal Carvalho <ja...@golang.org>
            Gerrit-Reviewer: Suzy Mueller <suz...@golang.org>
            Gerrit-Reviewer: kokoro <noreply...@google.com>
            Gerrit-CC: Gopher Robot <go...@golang.org>
            Gerrit-MessageType: merged
            Reply all
            Reply to author
            Forward
            0 new messages