Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fabric8-analytics-lsp-server

Package Overview
Dependencies
Maintainers
3
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fabric8-analytics-lsp-server - npm Package Compare versions

Comparing version 0.3.2 to 0.4.0

aggregators.js

37

collector.js

@@ -12,2 +12,3 @@ /* --------------------------------------------------------------------------------------------

const utils_1 = require("./utils");
const child_process_1 = require("child_process");
/* Please note :: There was issue with semverRegex usage in the code. During run time, it extracts

@@ -72,8 +73,7 @@ * version with 'v' prefix, but this is not be behavior of semver in CLI and test environment.

class NaiveGomodParser {
constructor(contents) {
this.dependencies = NaiveGomodParser.parseDependencies(contents);
constructor(contents, goImports) {
this.dependencies = NaiveGomodParser.parseDependencies(contents, goImports);
}
static parseDependencies(contents) {
const gomod = contents.split("\n");
return gomod.reduce((dependencies, line, index) => {
static parseDependencies(contents, goImports) {
return contents.split("\n").reduce((dependencies, line, index) => {
// Ignore "replace" lines

@@ -99,2 +99,11 @@ if (!line.includes("=>")) {

dependencies.push(new Dependency(entry));
// Find packages of this module.
goImports.forEach(pckg => {
if (pckg != pkgName && pckg.startsWith(pkgName + "/")) {
const entry = new types_1.KeyValueEntry(pckg, { line: 0, column: 0 });
entry.value = new types_1.Variant(types_1.ValueType.String, 'v' + version[0]);
entry.value_position = { line: index + 1, column: version.index };
dependencies.push(new Dependency(entry));
}
});
}

@@ -113,7 +122,21 @@ }

class GomodDependencyCollector {
constructor(classes = ["dependencies"]) {
constructor(manifestFile, classes = ["dependencies"]) {
this.manifestFile = manifestFile;
this.classes = classes;
this.manifestFile = manifestFile;
}
async collect(contents) {
let parser = new NaiveGomodParser(contents);
let promiseExec = new Promise((resolve, reject) => {
const vscodeRootpath = this.manifestFile.replace("file://", "").replace("/go.mod", "");
child_process_1.exec(`go list -f '{{ join .Imports "\\n" }}' ./...`, { cwd: vscodeRootpath, maxBuffer: 1024 * 1200 }, (error, stdout, stderr) => {
if (error) {
reject(`'go list' command failed with error :: ${stderr}`);
}
else {
resolve(new Set(stdout.toString().split("\n")));
}
});
});
const goImports = await promiseExec;
let parser = new NaiveGomodParser(contents, goImports);
return parser.parse();

@@ -120,0 +143,0 @@ }

120

consumers.js

@@ -7,4 +7,5 @@ /* --------------------------------------------------------------------------------------------

Object.defineProperty(exports, "__esModule", { value: true });
exports.codeActionsMap = exports.EmptyResultEngine = exports.SecurityEngine = exports.DiagnosticsPipeline = void 0;
exports.codeActionsMap = exports.SecurityEngine = exports.DiagnosticsPipeline = void 0;
const utils_1 = require("./utils");
const vulnerability_1 = require("./vulnerability");
const vscode_languageserver_1 = require("vscode-languageserver");

@@ -31,3 +32,3 @@ ;

class DiagnosticsPipeline {
constructor(classes, dependency, config, diags, uri) {
constructor(classes, dependency, config, diags, vulnerabilityAggregator, uri) {
this.items = classes.map((i) => { return new i(dependency, config); });

@@ -38,2 +39,3 @@ this.dependency = dependency;

this.uri = uri;
this.vulnerabilityAggregator = vulnerabilityAggregator;
}

@@ -43,7 +45,41 @@ run(data) {

if (item.consume(data)) {
for (let d of item.produce(this.uri))
this.diagnostics.push(d);
for (let d of item.produce()) {
const aggVulnerability = this.vulnerabilityAggregator.aggregate(d);
const aggDiagnostic = aggVulnerability.getDiagnostic();
// Add/Update quick action for given aggregated diangnostic
// TODO: this can be done lazily
if (aggVulnerability.recommendedVersion && (aggVulnerability.vulnerabilityCount > 0 || aggVulnerability.exploitCount != null)) {
let codeAction = {
title: `Switch to recommended version ${aggVulnerability.recommendedVersion}`,
diagnostics: [aggDiagnostic],
kind: vscode_languageserver_1.CodeActionKind.QuickFix,
edit: {
changes: {}
}
};
codeAction.edit.changes[this.uri] = [{
range: aggDiagnostic.range,
newText: aggVulnerability.recommendedVersion
}];
// We will have line|start as key instead of message
codeActionsMap[aggDiagnostic.range.start.line + "|" + aggDiagnostic.range.start.character] = codeAction;
}
if (this.vulnerabilityAggregator.isNewVulnerability) {
this.diagnostics.push(aggDiagnostic);
}
else {
// Update the existing diagnostic object based on range values
this.diagnostics.forEach((diag, index) => {
if (diag.range.start.line == aggVulnerability.range.start.line &&
diag.range.start.character == aggVulnerability.range.start.character) {
this.diagnostics[index] = aggDiagnostic;
return;
}
});
}
}
}
}
return this.diagnostics;
// This is not used by any one.
return [];
}

@@ -57,2 +93,4 @@ }

this.config = config;
this.package = null;
this.version = null;
this.changeTo = null;

@@ -71,2 +109,8 @@ this.message = null;

}
if (this.packageBinding != null) {
this.package = bind_object(data, this.packageBinding);
}
if (this.versionBinding != null) {
this.version = bind_object(data, this.versionBinding);
}
if (this.changeToBinding != null) {

@@ -94,24 +138,2 @@ this.changeTo = bind_object(data, this.changeToBinding);

;
/* We've received an empty/unfinished result, display that analysis is pending */
class EmptyResultEngine extends AnalysisConsumer {
constructor(context, config) {
super(config);
this.context = context;
}
produce() {
if (this.item == {} && (this.item.finished_at === undefined ||
this.item.finished_at == null)) {
return [{
severity: vscode_languageserver_1.DiagnosticSeverity.Information,
range: utils_1.get_range(this.context.version),
message: `Application dependency ${this.context.name.value}-${this.context.version.value} - analysis is pending`,
source: 'Dependency Analytics Plugin [Powered by Snyk]'
}];
}
else {
return [];
}
}
}
exports.EmptyResultEngine = EmptyResultEngine;
/* Report CVEs in found dependencies */

@@ -123,2 +145,4 @@ class SecurityEngine extends AnalysisConsumer {

this.binding = { path: ['vulnerability'] };
this.packageBinding = { path: ['package'] };
this.versionBinding = { path: ['version'] };
/* recommendation to use a different version */

@@ -137,43 +161,5 @@ this.changeToBinding = { path: ['recommended_versions'] };

}
produce(ctx) {
produce() {
if (this.item.length > 0) {
/* The diagnostic's severity. */
let diagSeverity;
if (this.vulnerabilityCount == 0 && this.advisoryCount > 0) {
diagSeverity = vscode_languageserver_1.DiagnosticSeverity.Information;
}
else {
diagSeverity = vscode_languageserver_1.DiagnosticSeverity.Error;
}
const recommendedVersion = this.changeTo || "N/A";
const exploitCount = this.exploitCount || "unavailable";
const msg = `${this.context.name.value}: ${this.context.version.value}
Known security vulnerability: ${this.vulnerabilityCount}
Security advisory: ${this.advisoryCount}
Exploits: ${exploitCount}
Highest severity: ${this.highestSeverity}
Recommendation: ${recommendedVersion}`;
let diagnostic = {
severity: diagSeverity,
range: utils_1.get_range(this.context.version),
message: msg,
source: '\nDependency Analytics Plugin [Powered by Snyk]',
};
// TODO: this can be done lazily
if (this.changeTo && (this.vulnerabilityCount > 0 || this.exploitCount != null)) {
let codeAction = {
title: "Switch to recommended version " + this.changeTo,
diagnostics: [diagnostic],
kind: vscode_languageserver_1.CodeActionKind.QuickFix,
edit: {
changes: {}
}
};
codeAction.edit.changes[ctx] = [{
range: diagnostic.range,
newText: this.changeTo
}];
codeActionsMap[diagnostic.message] = codeAction;
}
return [diagnostic];
return [new vulnerability_1.Vulnerability(this.package, this.version, 1, this.vulnerabilityCount, this.advisoryCount, this.exploitCount, this.highestSeverity, this.changeTo, utils_1.get_range(this.context.version))];
}

@@ -180,0 +166,0 @@ else {

{
"name": "fabric8-analytics-lsp-server",
"description": "LSP Server for Dependency Analytics",
"version": "0.3.2",
"version": "0.4.0",
"author": "Pavel Odvody",

@@ -37,3 +37,4 @@ "contributors": [

"winston": "3.2.1",
"xml2object": "0.1.2"
"xml2object": "0.1.2",
"compare-versions": "3.6.0"
},

@@ -51,3 +52,4 @@ "devDependencies": {

"ts-node": "^8.3.0",
"typescript": "^3.6.3"
"typescript": "^3.6.3",
"fake-exec": "^1.1.0"
},

@@ -54,0 +56,0 @@ "scripts": {

@@ -12,5 +12,5 @@ /* --------------------------------------------------------------------------------------------

const consumers_1 = require("./consumers");
const aggregators_1 = require("./aggregators");
const node_fetch_1 = require("node-fetch");
const url = require('url');
const https = require('https');
const winston = require('winston');

@@ -192,6 +192,6 @@ let transport;

/* Runs DiagnosticPileline to consume response and generate Diagnostic[] */
function runPipeline(response, diagnostics, diagnosticFilePath, dependencyMap, totalCount) {
function runPipeline(response, diagnostics, packageAggregator, diagnosticFilePath, dependencyMap, totalCount) {
response.forEach(r => {
const dependency = dependencyMap.get(r.package + r.version);
let pipeline = new consumers_1.DiagnosticsPipeline(DiagnosticsEngines, dependency, config, diagnostics, diagnosticFilePath);
let pipeline = new consumers_1.DiagnosticsPipeline(DiagnosticsEngines, dependency, config, diagnostics, packageAggregator, diagnosticFilePath);
pipeline.run(r);

@@ -221,7 +221,23 @@ for (const item of pipeline.items) {

connection.sendNotification('caNotification', { 'data': caDefaultMsg });
const deps = await collector.collect(contents);
let deps = null;
try {
deps = await collector.collect(contents);
}
catch (error) {
// Error can be raised during golang `go list ` command only.
if (ecosystem == "golang") {
console.error("Command execution failed, something wrong with manifest file go.mod\n%s", error);
connection.sendNotification('caError', { 'data': 'Unable to execute `go list` command, run `go mod tidy` to resolve dependencies issues' });
return;
}
}
let validPackages = deps;
let packageAggregator = null;
if (ecosystem != "golang") {
validPackages = deps.filter(d => regexVersion.test(d.version.value.trim()));
packageAggregator = new aggregators_1.NoopVulnerabilityAggregator();
}
else {
packageAggregator = new aggregators_1.GolangVulnerabilityAggregator();
}
const requestPayload = validPackages.map(d => ({ "package": d.name.value, "version": d.version.value }));

@@ -233,3 +249,3 @@ const requestMapper = new Map(validPackages.map(d => [d.name.value + d.version.value, d]));

const start = new Date().getTime();
const allRequests = slicePayload(requestPayload, batchSize, ecosystem).map(request => fetchVulnerabilities(request).then(response => runPipeline(response, diagnostics, diagnosticFilePath, requestMapper, totalCount)));
const allRequests = slicePayload(requestPayload, batchSize, ecosystem).map(request => fetchVulnerabilities(request).then(response => runPipeline(response, diagnostics, packageAggregator, diagnosticFilePath, requestMapper, totalCount)));
await Promise.allSettled(allRequests);

@@ -250,3 +266,3 @@ const end = new Date().getTime();

files.on(EventStream.Diagnostics, "^go\\.mod$", (uri, name, contents) => {
sendDiagnostics('golang', uri, contents, new collector_1.GomodDependencyCollector());
sendDiagnostics('golang', uri, contents, new collector_1.GomodDependencyCollector(uri));
});

@@ -273,3 +289,3 @@ let checkDelay;

for (let diagnostic of params.context.diagnostics) {
let codeAction = consumers_1.codeActionsMap[diagnostic.message];
let codeAction = consumers_1.codeActionsMap[diagnostic.range.start.line + "|" + diagnostic.range.start.character];
if (codeAction != null) {

@@ -276,0 +292,0 @@ codeActions.push(codeAction);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc