diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java new file mode 100644 index 000000000..3406b9900 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java @@ -0,0 +1,66 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.exception; + +/** + * An exception used when a dependency could not be found. + * + * @author Jeremy Long + */ +public class DependencyNotFoundException extends Exception { + + /** + * The serial version uid. + */ + private static final long serialVersionUID = 1L; + + /** + * Creates a new DependencyNotFoundException. + */ + public DependencyNotFoundException() { + super(); + } + + /** + * Creates a new DependencyNotFoundException. + * + * @param msg a message for the exception. + */ + public DependencyNotFoundException(String msg) { + super(msg); + } + + /** + * Creates a new DependencyNotFoundException. + * + * @param ex the cause of the exception. + */ + public DependencyNotFoundException(Throwable ex) { + super(ex); + } + + /** + * Creates a new DependencyNotFoundException. + * + * @param msg a message for the exception. + * @param ex the cause of the exception. + */ + public DependencyNotFoundException(String msg, Throwable ex) { + super(msg, ex); + } +} diff --git a/dependency-check-maven/src/it/729-system-scope-resolved/invoker.properties b/dependency-check-maven/src/it/729-system-scope-resolved/invoker.properties new file mode 100644 index 000000000..135fb86f1 --- /dev/null +++ b/dependency-check-maven/src/it/729-system-scope-resolved/invoker.properties @@ -0,0 +1,19 @@ +# +# This file is part of dependency-check-maven. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Copyright (c) 2017 Jeremy Long. All Rights Reserved. +# + +invoker.goals = install ${project.groupId}:${project.artifactId}:${project.version}:check -e -Dformat=JSON diff --git a/dependency-check-maven/src/it/729-system-scope/pom.xml b/dependency-check-maven/src/it/729-system-scope-resolved/pom.xml similarity index 100% rename from dependency-check-maven/src/it/729-system-scope/pom.xml rename to dependency-check-maven/src/it/729-system-scope-resolved/pom.xml diff --git a/dependency-check-maven/src/it/729-system-scope-resolved/postbuild.groovy b/dependency-check-maven/src/it/729-system-scope-resolved/postbuild.groovy new file mode 100644 index 000000000..c1d6476e4 --- /dev/null +++ b/dependency-check-maven/src/it/729-system-scope-resolved/postbuild.groovy @@ -0,0 +1,30 @@ +/* + * This file is part of dependency-check-maven. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. + */ + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import java.nio.charset.Charset; +import groovy.json.JsonSlurper; + +def slurper = new JsonSlurper() +def json = slurper.parse(new File(basedir, "target/dependency-check-report.json"), "UTF-8") + +assert json instanceof Map +assert json.analysis.dependencies instanceof List +assert json.analysis.dependencies.size()==1 +return true; diff --git a/dependency-check-maven/src/it/729-system-scope-resolved/prebuild.groovy b/dependency-check-maven/src/it/729-system-scope-resolved/prebuild.groovy new file mode 100644 index 000000000..9ec3a0a91 --- /dev/null +++ b/dependency-check-maven/src/it/729-system-scope-resolved/prebuild.groovy @@ -0,0 +1,17 @@ +/* + * This file is part of dependency-check-maven. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. + */ diff --git a/dependency-check-maven/src/it/729-system-scope/invoker.properties b/dependency-check-maven/src/it/729-system-scope-skipped/invoker.properties similarity index 100% rename from dependency-check-maven/src/it/729-system-scope/invoker.properties rename to dependency-check-maven/src/it/729-system-scope-skipped/invoker.properties diff --git a/dependency-check-maven/src/it/729-system-scope-skipped/pom.xml b/dependency-check-maven/src/it/729-system-scope-skipped/pom.xml new file mode 100644 index 000000000..6f2d06950 --- /dev/null +++ b/dependency-check-maven/src/it/729-system-scope-skipped/pom.xml @@ -0,0 +1,34 @@ + + + + 4.0.0 + org.owasp.test + test-system-scope + 1.0.0-SNAPSHOT + jar + + + system + com.sun + tools + 1.8 + ${java.home}/../lib/tools.jar + + + \ No newline at end of file diff --git a/dependency-check-maven/src/it/729-system-scope/postbuild.groovy b/dependency-check-maven/src/it/729-system-scope-skipped/postbuild.groovy similarity index 100% rename from dependency-check-maven/src/it/729-system-scope/postbuild.groovy rename to dependency-check-maven/src/it/729-system-scope-skipped/postbuild.groovy diff --git a/dependency-check-maven/src/it/729-system-scope/prebuild.groovy b/dependency-check-maven/src/it/729-system-scope-skipped/prebuild.groovy similarity index 100% rename from dependency-check-maven/src/it/729-system-scope/prebuild.groovy rename to dependency-check-maven/src/it/729-system-scope-skipped/prebuild.groovy diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java index 741e832a3..3c1e89fd0 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java @@ -55,6 +55,7 @@ import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; +import org.owasp.dependencycheck.exception.DependencyNotFoundException; import org.owasp.dependencycheck.exception.ExceptionCollection; import org.owasp.dependencycheck.exception.ReportException; import org.owasp.dependencycheck.reporting.ReportGenerator; @@ -643,16 +644,45 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma } exCol = collectDependencies(engine, project, dependencyNode.getChildren(), buildingRequest); try { - final ArtifactCoordinate coordinate = TransferUtils.toArtifactCoordinate(dependencyNode.getArtifact()); - final Artifact result = artifactResolver.resolveArtifact(buildingRequest, coordinate).getArtifact(); - if (result.isResolved() && result.getFile() != null) { - final List deps = engine.scan(result.getFile().getAbsoluteFile(), + boolean isResolved = false; + File artifactFile = null; + String artifactId = null; + String groupId = null; + String version = null; + if (org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals(dependencyNode.getArtifact().getScope())) { + for (org.apache.maven.model.Dependency d : project.getDependencies()) { + Artifact a = dependencyNode.getArtifact(); + if (d.getSystemPath() != null && artifactsMatch(d, a)) { + + artifactFile = new File(d.getSystemPath()); + isResolved = artifactFile.isFile(); + groupId = a.getGroupId(); + artifactId = a.getArtifactId(); + version = a.getVersion(); + break; + } + } + if (!isResolved) { + getLog().error("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString()); + exCol.addException(new DependencyNotFoundException("Unable to resolve system scoped dependency: " + dependencyNode.toNodeString())); + } + } else { + final ArtifactCoordinate coordinate = TransferUtils.toArtifactCoordinate(dependencyNode.getArtifact()); + final Artifact result = artifactResolver.resolveArtifact(buildingRequest, coordinate).getArtifact(); + isResolved = result.isResolved(); + artifactFile = result.getFile(); + groupId = result.getGroupId(); + artifactId = result.getArtifactId(); + version = result.getVersion(); + } + if (isResolved && artifactFile != null) { + final List deps = engine.scan(artifactFile.getAbsoluteFile(), project.getName() + ":" + dependencyNode.getArtifact().getScope()); if (deps != null) { if (deps.size() == 1) { final Dependency d = deps.get(0); if (d != null) { - final MavenArtifact ma = new MavenArtifact(result.getGroupId(), result.getArtifactId(), result.getVersion()); + final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version); d.addAsEvidence("pom", ma, Confidence.HIGHEST); if (getLog().isDebugEnabled()) { getLog().debug(String.format("Adding project reference %s on dependency %s", @@ -690,6 +720,33 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma return exCol; } + /** + * Determines if the groupId, artifactId, and version of the Maven + * dependency and artifact match. + * + * @param d the Maven dependency + * @param a the Maven artifact + * @return true if the groupId, artifactId, and version match + */ + private static boolean artifactsMatch(org.apache.maven.model.Dependency d, Artifact a) { + return (isEqualOrNull(a.getArtifactId(), d.getArtifactId())) + && (isEqualOrNull(a.getGroupId(), d.getGroupId())) + && (isEqualOrNull(a.getVersion(), d.getVersion())); + } + + /** + * Compares two strings for equality; if both strings are null they are + * considered equal. + * + * @param left the first string to compare + * @param right the second string to compare + * @return true if the strings are equal or if they are both null; otherwise + * false. + */ + private static boolean isEqualOrNull(String left, String right) { + return (left != null && left.equals(right)) || (left == null && right == null); + } + /** * @return Returns a new ProjectBuildingRequest populated from the current * session and the current project remote repositories, used to resolve