Skip to content

Commit 34febf5

Browse files
committed
devonfw#103: Security Entry and determination of version Range for vulnerability
1 parent e5c70e7 commit 34febf5

File tree

2 files changed

+115
-20
lines changed

2 files changed

+115
-20
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.devonfw.tools.ide.url.model.file;
2+
3+
import com.devonfw.tools.ide.version.VersionRange;
4+
5+
/**
6+
* A simple container with the information about a security entry.
7+
*
8+
* @param versionRange The version range of affected versions.
9+
* @param severity The severity of the security issue (0.0 - 10.0).
10+
* @param severityVersion The version of the severity. As of November 2023 its either v2 or v3.
11+
* @param cveName The CVE name.
12+
* @param Description The description of the security issue.
13+
* @param url The url to the security issue.
14+
*/
15+
public record SecurityEntry(VersionRange versionRange, double severity, String severityVersion, String cveName,
16+
String Description, String url) {
17+
}

security/src/main/java/com/devonfw/tools/security/Main.java

+98-20
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package com.devonfw.tools.security;
22

3+
import java.nio.file.Path;
4+
import java.nio.file.Paths;
35
import java.util.List;
4-
import java.util.stream.Collectors;
6+
import java.util.Set;
57

68
import com.devonfw.tools.ide.context.IdeContext;
79
import com.devonfw.tools.ide.context.IdeContextConsole;
10+
import com.devonfw.tools.ide.json.mapping.JsonMapping;
811
import com.devonfw.tools.ide.log.IdeLogLevel;
12+
import com.devonfw.tools.ide.url.model.file.SecurityEntry;
913
import com.devonfw.tools.ide.url.updater.UpdateManager;
14+
import com.devonfw.tools.ide.version.VersionIdentifier;
15+
import com.devonfw.tools.ide.version.VersionRange;
16+
import com.fasterxml.jackson.core.JsonProcessingException;
17+
import com.fasterxml.jackson.databind.ObjectMapper;
1018
import org.owasp.dependencycheck.Engine;
1119
import org.owasp.dependencycheck.analyzer.AnalysisPhase;
1220
import org.owasp.dependencycheck.analyzer.FileNameAnalyzer;
@@ -49,31 +57,101 @@ public static void main(String[] args) {
4957
float minV3Severity = 0.0f;
5058

5159
for (Dependency dependency : engine.getDependencies()) {
52-
List<Vulnerability> noSeverity = dependency.getVulnerabilities(true).stream()
53-
.filter(v -> v.getCvssV2() == null && v.getCvssV3() == null).collect(Collectors.toList());
54-
List<Vulnerability> onlyV2Severity = dependency.getVulnerabilities(true).stream()
55-
.filter(v -> v.getCvssV2() != null && v.getCvssV3() == null).collect(Collectors.toList());
56-
List<Vulnerability> hasV3Severity = dependency.getVulnerabilities(true).stream()
57-
.filter(v -> v.getCvssV3() != null).collect(Collectors.toList());
58-
59-
if (!noSeverity.isEmpty()) {
60-
System.out.println("no severity is not empty: " + dependency.getFileName());
61-
System.exit(1);
62-
}
63-
64-
onlyV2Severity.removeIf(v -> v.getCvssV2().getScore() < minV3Severity);
65-
hasV3Severity.removeIf(v -> v.getCvssV3().getBaseScore() < minV2Severity);
60+
Set<Vulnerability> vulnerabilities = dependency.getVulnerabilities(true);
6661

67-
System.out.println("There were vulnerabilities found in: " + dependency.getFileName());
68-
onlyV2Severity.forEach(v -> System.out.println("V2: " + v.getName() + " " + v.getCvssV2().getScore()));
69-
hasV3Severity.forEach(v -> System.out.println("V3: " + v.getName() + " " + v.getCvssV3().getBaseScore()));
62+
String filePath = dependency.getFilePath();
63+
Path parent = Paths.get(filePath).getParent();
64+
String tool = parent.getParent().getParent().getFileName().toString();
65+
String edition = parent.getParent().getFileName().toString();
66+
List<VersionIdentifier> sortedVersions = ideContext.getUrls().getSortedVersions(tool, edition);
7067

71-
// TODO read min levels from console
68+
// TODO read min levels from console or args[]
7269
// TODO list all vulnerabilities, so maybe description, all fields of cvssv3 and cvssv2, cve name, source,
7370
// url of vulnerabilityIds, and vulnerableSoftware
7471
// TODO take all vulnerabilities, or ask for another min level und update the numbers of vulnerabilities
7572
// TODO write vulnerabilities to file -> new format? that includes CVE name?
7673

74+
// List<SecurityEntry> foundVulnerabilities = new ArrayList<>();
75+
76+
for (Vulnerability vulnerability : vulnerabilities) {
77+
78+
if (vulnerability.getCvssV2() == null && vulnerability.getCvssV3() == null) {
79+
throw new RuntimeException("Vulnerability without severity found: " + vulnerability.getName());
80+
}
81+
boolean hasV3Severity = vulnerability.getCvssV3() != null;
82+
double severity = hasV3Severity
83+
? vulnerability.getCvssV3().getBaseScore()
84+
: vulnerability.getCvssV2().getScore();
85+
String severityVersion = hasV3Severity ? "v3" : "v2";
86+
String cveName = vulnerability.getName();
87+
String description = vulnerability.getDescription();
88+
89+
boolean toLowSeverity = hasV3Severity ? severity < minV3Severity : severity < minV2Severity;
90+
if (toLowSeverity) {
91+
continue;
92+
}
93+
94+
VersionRange versionRange = getVersionRangeFromVulnerability(sortedVersions, vulnerability);
95+
SecurityEntry securityEntry = new SecurityEntry(versionRange, severity, severityVersion, cveName, description,
96+
null);
97+
ObjectMapper mapper = JsonMapping.create();
98+
try {
99+
String jsonString = mapper.writeValueAsString(securityEntry);
100+
System.out.println(jsonString);
101+
} catch (JsonProcessingException e) {
102+
throw new RuntimeException(e);
103+
}
104+
}
77105
}
106+
engine.close();
78107
}
79-
}
108+
109+
static VersionRange getVersionRangeFromInterval(List<VersionIdentifier> sortedVersions, String vStartExcluding, String vStartIncluding,
110+
String vEndIncluding, String vEndExcluding) {
111+
112+
VersionIdentifier max = null;
113+
if (vEndIncluding != null) {
114+
max = VersionIdentifier.of(vEndIncluding); // this allows that max is not part of the available versions, this has no impact on the contains method but maybe confusing
115+
} else if (vEndExcluding != null) {
116+
VersionIdentifier end = VersionIdentifier.of(vEndExcluding);
117+
for (VersionIdentifier version : sortedVersions) {
118+
if (version.isLess(end)) {
119+
max = version;
120+
break;
121+
}
122+
}
123+
}
124+
125+
VersionIdentifier min = null;
126+
if (vStartIncluding != null) {
127+
min = VersionIdentifier.of(vStartIncluding);
128+
} else if (vStartExcluding != null) {
129+
for (int i = sortedVersions.size() - 1; i >= 0; i--) {
130+
VersionIdentifier version = sortedVersions.get(i);
131+
if (version.isGreater(VersionIdentifier.of(vStartExcluding))) {
132+
min = version;
133+
break;
134+
}
135+
}
136+
}
137+
return new VersionRange(min, max);
138+
}
139+
140+
static VersionRange getVersionRangeFromVulnerability(List<VersionIdentifier> sortedVersions,
141+
Vulnerability vulnerability) {
142+
143+
VulnerableSoftware matchedVulnerableSoftware = vulnerability.getMatchedVulnerableSoftware();
144+
String vEndExcluding = matchedVulnerableSoftware.getVersionEndExcluding();
145+
String vEndIncluding = matchedVulnerableSoftware.getVersionEndIncluding();
146+
String vStartExcluding = matchedVulnerableSoftware.getVersionStartExcluding();
147+
String vStartIncluding = matchedVulnerableSoftware.getVersionStartIncluding();
148+
149+
if (vEndExcluding == null && vEndIncluding == null && vStartExcluding == null && vStartIncluding == null) {
150+
throw new RuntimeException("Vulnerability without version range found: " + vulnerability.getName());
151+
}
152+
153+
return getVersionRangeFromInterval(sortedVersions, vStartExcluding, vStartIncluding, vEndIncluding,
154+
vEndExcluding);
155+
}
156+
}
157+

0 commit comments

Comments
 (0)