Skip to content

Commit e23c08d

Browse files
authored
fix: validate executable binary in the path before running the analysis. (#134)
## Description fix: validate executable binary in the path before running the analysis. **Related issue (if any):** redhat-developer/intellij-dependency-analytics#182 ## Checklist - [x] I have followed this repository's contributing guidelines. - [x] I will adhere to the project's code of conduct. ## Additional information > Anything else? Signed-off-by: Chao Wang <chaowan@redhat.com>
1 parent 00a18a8 commit e23c08d

15 files changed

Lines changed: 299 additions & 60 deletions

src/main/java/com/redhat/exhort/image/ImageUtils.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ public class ImageUtils {
5555
"application/vnd.oci.image.manifest.v1+json";
5656
private static final String MEDIA_TYPE_OCI1_MANIFEST_LIST =
5757
"application/vnd.oci.image.index.v1+json";
58+
private static final String DOCKER = "docker";
59+
private static final String PODMAN = "podman";
60+
private static final String SYFT = "syft";
61+
private static final String SKOPEO = "skopeo";
62+
public static final String SKIP_VALIDATION_KEY = "skip.binary.validation";
63+
public static final String ARG_VERSION = "--version";
5864

5965
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
6066

@@ -124,9 +130,9 @@ public static JsonNode generateImageSBOM(ImageRef imageRef)
124130
}
125131

126132
static Operations.ProcessExecOutput execSyft(ImageRef imageRef) {
127-
var syft = Operations.getCustomPathOrElse("syft");
128-
var docker = Operations.getCustomPathOrElse("docker");
129-
var podman = Operations.getCustomPathOrElse("podman");
133+
var syft = Operations.getExecutable(SYFT, ARG_VERSION);
134+
var docker = Operations.getExecutable(DOCKER, ARG_VERSION);
135+
var podman = Operations.getExecutable(PODMAN, ARG_VERSION);
130136

131137
var syftConfigPath = Environment.get(EXHORT_SYFT_CONFIG_PATH, "");
132138
var imageSource = Environment.get(EXHORT_SYFT_IMAGE_SOURCE, "");
@@ -232,7 +238,7 @@ public static Platform getImagePlatform() {
232238
}
233239

234240
static String hostInfo(String engine, String info) {
235-
var exec = Operations.getCustomPathOrElse(engine);
241+
var exec = Operations.getExecutable(engine, ARG_VERSION);
236242
var cmd = new String[] {exec, "info"};
237243

238244
var output = Operations.runProcessGetFullOutput(null, cmd, null);
@@ -251,31 +257,31 @@ static String hostInfo(String engine, String info) {
251257
}
252258

253259
static String dockerGetOs() {
254-
return hostInfo("docker", "OSType");
260+
return hostInfo(DOCKER, "OSType");
255261
}
256262

257263
static String dockerGetArch() {
258-
var arch = hostInfo("docker", "Architecture");
264+
var arch = hostInfo(DOCKER, "Architecture");
259265
arch = archMapping.get(arch);
260266
return Objects.requireNonNullElse(arch, "");
261267
}
262268

263269
static String dockerGetVariant() {
264-
var variant = hostInfo("docker", "Architecture");
270+
var variant = hostInfo(DOCKER, "Architecture");
265271
variant = variantMapping.get(variant);
266272
return Objects.requireNonNullElse(variant, "");
267273
}
268274

269275
static String podmanGetOs() {
270-
return hostInfo("podman", "os");
276+
return hostInfo(PODMAN, "os");
271277
}
272278

273279
static String podmanGetArch() {
274-
return hostInfo("podman", "arch");
280+
return hostInfo(PODMAN, "arch");
275281
}
276282

277283
static String podmanGetVariant() {
278-
return hostInfo("podman", "variant");
284+
return hostInfo(PODMAN, "variant");
279285
}
280286

281287
static String dockerPodmanInfo(Supplier<String> dockerSupplier, Supplier<String> podmanSupplier) {
@@ -416,7 +422,7 @@ static Map<Platform, String> getSingleImageDigest(ImageRef imageRef)
416422
}
417423

418424
static Operations.ProcessExecOutput execSkopeoInspect(ImageRef imageRef, boolean raw) {
419-
var skopeo = Operations.getCustomPathOrElse("skopeo");
425+
var skopeo = Operations.getExecutable(SKOPEO, ARG_VERSION);
420426

421427
var configPath = Environment.get(EXHORT_SKOPEO_CONFIG_PATH, "");
422428
var daemonHost = Environment.get(EXHORT_IMAGE_SERVICE_ENDPOINT, "");

src/main/java/com/redhat/exhort/providers/GoModulesProvider.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@
4848
public final class GoModulesProvider extends Provider {
4949

5050
public static final String PROP_EXHORT_GO_MVS_LOGIC_ENABLED = "EXHORT_GO_MVS_LOGIC_ENABLED";
51-
private Logger log = LoggersFactory.getLogger(this.getClass().getName());
51+
private static final Logger log = LoggersFactory.getLogger(GoModulesProvider.class.getName());
5252
private static final String GO_HOST_ARCHITECTURE_ENV_NAME = "GOHOSTARCH";
5353
private static final String GO_HOST_OPERATION_SYSTEM_ENV_NAME = "GOHOSTOS";
5454
public static final String DEFAULT_MAIN_VERSION = "v0.0.0";
5555
private final TreeMap<String, String> goEnvironmentVariableForPurl;
56+
private final String goExecutable;
5657

5758
public String getMainModuleVersion() {
5859
return mainModuleVersion;
@@ -62,6 +63,7 @@ public String getMainModuleVersion() {
6263

6364
public GoModulesProvider(Path manifest) {
6465
super(Type.GOLANG, manifest);
66+
this.goExecutable = Operations.getExecutable("go", "version");
6567
this.goEnvironmentVariableForPurl = getQualifiers(true);
6668
this.mainModuleVersion = getDefaultMainModuleVersion();
6769
}
@@ -378,11 +380,9 @@ private static List<String> collectAllDirectDependencies(List<String> targetLine
378380
.collect(Collectors.toList());
379381
}
380382

381-
private static TreeMap<String, String> getQualifiers(boolean includeOsAndArch) {
382-
383+
private TreeMap<String, String> getQualifiers(boolean includeOsAndArch) {
383384
if (includeOsAndArch) {
384-
var go = Operations.getCustomPathOrElse("go");
385-
String goEnvironmentVariables = Operations.runProcessGetOutput(null, go, "env");
385+
String goEnvironmentVariables = Operations.runProcessGetOutput(null, goExecutable, "env");
386386
String hostArch =
387387
getEnvironmentVariable(goEnvironmentVariables, GO_HOST_ARCHITECTURE_ENV_NAME);
388388
String hostOS =
@@ -405,9 +405,8 @@ private static String getEnvironmentVariable(String goEnvironmentVariables, Stri
405405

406406
private String buildGoModulesDependencies(Path manifestPath)
407407
throws JsonMappingException, JsonProcessingException {
408-
var go = Operations.getCustomPathOrElse("go");
409408
String[] goModulesDeps;
410-
goModulesDeps = new String[] {go, "mod", "graph"};
409+
goModulesDeps = new String[] {goExecutable, "mod", "graph"};
411410

412411
// execute the clean command
413412
String goModulesOutput =

src/main/java/com/redhat/exhort/providers/GradleProvider.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@
2929
import java.io.IOException;
3030
import java.nio.file.Files;
3131
import java.nio.file.Path;
32-
import java.util.*;
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.Collections;
35+
import java.util.HashMap;
36+
import java.util.List;
37+
import java.util.Map;
3338
import java.util.function.Consumer;
3439
import java.util.logging.Logger;
3540
import java.util.regex.Matcher;
@@ -49,7 +54,9 @@ public final class GradleProvider extends BaseJavaProvider {
4954
public static final String[] COMPONENT_ANALYSIS_CONFIGURATIONS = {
5055
"api", "implementation", "compileOnlyApi", "compileOnly", "runtimeOnly"
5156
};
52-
private Logger log = LoggersFactory.getLogger(this.getClass().getName());
57+
private static final Logger log = LoggersFactory.getLogger(GradleProvider.class.getName());
58+
59+
private final String gradleExecutable = Operations.getExecutable("gradle", "--version");
5360

5461
public GradleProvider(Path manifest) {
5562
super(Type.GRADLE, manifest);
@@ -213,12 +220,10 @@ private String extractPackageName(String line) {
213220
}
214221

215222
private Path getDependencies(Path manifestPath) throws IOException {
216-
// check for custom gradle executable
217-
var gradle = Operations.getCustomPathOrElse("gradle");
218223
// create a temp file for storing the dependency tree in
219224
var tempFile = Files.createTempFile("exhort_graph_", null);
220225
// the command will create the dependency tree in the temp file
221-
String gradleCommand = gradle + " dependencies";
226+
String gradleCommand = gradleExecutable + " dependencies";
222227

223228
String[] cmdList = gradleCommand.split("\\s+");
224229
String gradleOutput =
@@ -228,10 +233,9 @@ private Path getDependencies(Path manifestPath) throws IOException {
228233
return tempFile;
229234
}
230235

231-
private Path getProperties(Path manifestPath) throws IOException {
236+
protected Path getProperties(Path manifestPath) throws IOException {
232237
Path propsTempFile = Files.createTempFile("propsfile", ".txt");
233-
var gradle = Operations.getCustomPathOrElse("gradle");
234-
String propCmd = gradle + " properties";
238+
String propCmd = gradleExecutable + " properties";
235239
String[] propCmdList = propCmd.split("\\s+");
236240
String properties =
237241
Operations.runProcessGetOutput(Path.of(manifestPath.getParent().toString()), propCmdList);

src/main/java/com/redhat/exhort/providers/JavaMavenProvider.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,19 @@
5151
public final class JavaMavenProvider extends BaseJavaProvider {
5252

5353
private static final String PROP_JAVA_HOME = "JAVA_HOME";
54-
private Logger log = LoggersFactory.getLogger(this.getClass().getName());
54+
private static final Logger log = LoggersFactory.getLogger(JavaMavenProvider.class.getName());
55+
private final String mvnExecutable;
5556

5657
public JavaMavenProvider(Path manifest) {
5758
super(Type.MAVEN, manifest);
59+
// check for custom mvn executable
60+
this.mvnExecutable = Operations.getExecutable("mvn", "-v");
5861
}
5962

6063
@Override
6164
public Content provideStack() throws IOException {
62-
// check for custom mvn executable
63-
var mvn = Operations.getCustomPathOrElse("mvn");
6465
// clean command used to clean build target
65-
var mvnCleanCmd = new String[] {mvn, "clean", "-f", manifest.toString()};
66+
var mvnCleanCmd = new String[] {mvnExecutable, "clean", "-f", manifest.toString()};
6667
var mvnEnvs = getMvnExecEnvs();
6768
// execute the clean command
6869
Operations.runProcess(mvnCleanCmd, mvnEnvs);
@@ -72,7 +73,7 @@ public Content provideStack() throws IOException {
7273
var mvnTreeCmd =
7374
new ArrayList<String>() {
7475
{
75-
add(mvn);
76+
add(mvnExecutable);
7677
add("org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree");
7778
add("-Dverbose");
7879
add("-DoutputType=text");
@@ -125,12 +126,10 @@ public Content provideComponent() throws IOException {
125126
}
126127

127128
private Content generateSbomFromEffectivePom() throws IOException {
128-
// check for custom mvn executable
129-
var mvn = Operations.getCustomPathOrElse("mvn");
130129
var tmpEffPom = Files.createTempFile("exhort_eff_pom_", ".xml");
131130
var mvnEffPomCmd =
132131
new String[] {
133-
mvn,
132+
mvnExecutable,
134133
"clean",
135134
"help:effective-pom",
136135
String.format("-Doutput=%s", tmpEffPom.toString()),
@@ -313,6 +312,7 @@ Map<String, String> getMvnExecEnvs() {
313312

314313
// NOTE if we want to include "scope" tags in ignore,
315314
// add property here and a case in the start-element-switch in the getIgnored method
315+
316316
/** Aggregator class for aggregating Dependency data over stream iterations, * */
317317
private static final class DependencyAggregator {
318318
private String scope = "*";
@@ -324,7 +324,7 @@ private static final class DependencyAggregator {
324324
/**
325325
* Get the string representation of the dependency to use as excludes
326326
*
327-
* @return an exclude string for the dependency:tree plugin, ie. group-id:artifact-id:*:version
327+
* @return an exclude string for the dependency:tree plugin, i.e. group-id:artifact-id:*:version
328328
*/
329329
@Override
330330
public String toString() {
@@ -347,7 +347,7 @@ public PackageURL toPurl() {
347347
groupId,
348348
artifactId,
349349
version,
350-
this.scope == "*" ? null : new TreeMap<>(Map.of("scope", this.scope)),
350+
this.scope.equals("*") ? null : new TreeMap<>(Map.of("scope", this.scope)),
351351
null);
352352
} catch (MalformedPackageURLException e) {
353353
throw new IllegalArgumentException("Unable to parse PackageURL", e);

src/main/java/com/redhat/exhort/providers/JavaScriptProvider.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.github.packageurl.PackageURL;
2525
import com.redhat.exhort.Api;
2626
import com.redhat.exhort.Provider;
27+
import com.redhat.exhort.logging.LoggersFactory;
2728
import com.redhat.exhort.providers.javascript.model.Manifest;
2829
import com.redhat.exhort.sbom.Sbom;
2930
import com.redhat.exhort.sbom.SbomFactory;
@@ -42,6 +43,7 @@
4243
import java.util.Map;
4344
import java.util.Map.Entry;
4445
import java.util.TreeMap;
46+
import java.util.logging.Logger;
4547

4648
/**
4749
* Abstract implementation of the {@link Provider} used for converting dependency trees for
@@ -53,14 +55,14 @@ public abstract class JavaScriptProvider extends Provider {
5355
public static final String ENV_NODE_HOME = "NODE_HOME";
5456
private static final String PROP_PATH = "PATH";
5557

56-
private System.Logger log = System.getLogger(this.getClass().getName());
58+
private static final Logger log = LoggersFactory.getLogger(JavaScriptProvider.class.getName());
5759

5860
protected final String cmd;
5961
protected final Manifest manifest;
6062

6163
public JavaScriptProvider(Path manifest, Ecosystem.Type ecosystem, String cmd) {
6264
super(ecosystem, manifest);
63-
this.cmd = Operations.getCustomPathOrElse(cmd);
65+
this.cmd = Operations.getExecutable(cmd, "-v");
6466
try {
6567
this.manifest = new Manifest(manifest);
6668
} catch (IOException e) {
@@ -96,7 +98,7 @@ public Content provideComponent() throws IOException {
9698
Api.CYCLONEDX_MEDIA_TYPE);
9799
}
98100

99-
public static final PackageURL toPurl(String name, String version) {
101+
public static PackageURL toPurl(String name, String version) {
100102
try {
101103
String[] parts = name.split("/");
102104
if (parts.length == 2) {
@@ -109,7 +111,7 @@ public static final PackageURL toPurl(String name, String version) {
109111
}
110112
}
111113

112-
public static final PackageURL toPurl(String name) {
114+
public static PackageURL toPurl(String name) {
113115
try {
114116
return new PackageURL(String.format("pkg:%s/%s", Ecosystem.Type.NPM.getType(), name));
115117
} catch (MalformedPackageURLException e) {
@@ -208,7 +210,7 @@ protected Map<String, PackageURL> getRootDependencies(JsonNode depTree) {
208210
protected JsonNode buildDependencyTree(boolean includeTransitive)
209211
throws JsonMappingException, JsonProcessingException {
210212
// clean command used to clean build target
211-
Path manifestDir = null;
213+
Path manifestDir;
212214
try {
213215
// MacOS requires resolving to the CanonicalPath to avoid problems with /var
214216
// being a symlink
@@ -234,8 +236,7 @@ protected JsonNode buildDependencyTree(boolean includeTransitive)
234236
// execute the clean command
235237
String output = Operations.runProcessGetOutput(workDir, allDeps, getExecEnvAsArgs());
236238
if (debugLoggingIsNeeded()) {
237-
log.log(
238-
System.Logger.Level.INFO,
239+
log.info(
239240
String.format("Listed Install Packages in Json : %s %s", System.lineSeparator(), output));
240241
}
241242
output = parseDepTreeOutput(output);

0 commit comments

Comments
 (0)