Compare commits

...

78 Commits

Author SHA1 Message Date
Jeremy Long
3e4d012a69 Merge branch 'master' into reportGeneration 2017-05-23 21:02:49 -04:00
Jeremy Long
dccbd659ed Merge pull request #741 from sethjackson/patch-1
Update Windows usage.
2017-05-23 21:02:41 -04:00
Jeremy Long
1b84095c0e Merge branch 'master' into reportGeneration 2017-05-23 21:01:34 -04:00
Jeremy Long
c96ef88222 Moved report generation into the engine, cleaned up code, etc. 2017-05-23 21:00:40 -04:00
Jeremy Long
0540474e0c Merge pull request #742 from sethjackson/patch-2
Fix wording.
2017-05-23 20:31:17 -04:00
Seth Jackson
2dbfba9ac5 Fix wording. 2017-05-23 16:01:11 -04:00
Seth Jackson
8eff628303 Update Windows usage.
So that the example invocation works in PowerShell and cmd.
2017-05-23 14:43:02 -04:00
Jeremy Long
519167bf0f Merge pull request #739 from jeremylong/issue696-cli
Fix Boolean Properties in CLI
2017-05-21 19:32:38 -04:00
Jeremy Long
e8e06d12c7 updated for code coverage 2017-05-21 07:25:42 -04:00
Jeremy Long
006224b52c Merge branch 'master' into issue696-cli 2017-05-20 07:38:12 -04:00
Jeremy Long
6007be1b5f updated to resolve issue #696 2017-05-20 07:37:46 -04:00
Jeremy Long
6b5cfe1560 Merge pull request #735 from jeremylong/issue_718
Issue 718
2017-05-20 06:07:44 -04:00
Jeremy Long
f584be7f44 Merge pull request #734 from jeremylong/updateJsonReport
Update json report
2017-05-20 06:06:39 -04:00
Jeremy Long
b6a7d0ee9b Merge pull request #738 from sethjackson/suppress-unittestframework
Suppress UnitTestFramework false positives.
2017-05-20 06:06:13 -04:00
Seth Jackson
1402b20a6b Suppress UnitTestFramework false positives. 2017-05-18 13:42:20 -04:00
Jeremy Long
898412eaea default to remove auth schemas for proxy connections - added a property to disable this functionality. Fix for issue #718 2017-05-14 17:19:26 -04:00
Jeremy Long
7753b6f3c1 Merge branch 'master' into issue_718 2017-05-14 13:17:01 -04:00
Jeremy Long
ea93f315d5 updated test case for new report format 2017-05-14 09:27:51 -04:00
Jeremy Long
7f9cf5bb14 Merge branch 'master' into updateJsonReport 2017-05-14 09:26:27 -04:00
Jeremy Long
c4fe921670 updated report template 2017-05-14 09:25:56 -04:00
Jeremy Long
693c08cfd3 Merge pull request #731 from jeremylong/issue_729
Issue 729
2017-05-14 09:24:15 -04:00
Jeremy Long
9776f38b97 Merge pull request #726 from sethjackson/suppress-ef
Suppress EntityFramework false positives.
2017-05-14 08:52:40 -04:00
Jeremy Long
ff91d7cda7 Merge pull request #727 from sethjackson/patch-1
Update Windows development usage.
2017-05-14 08:51:56 -04:00
Jeremy Long
e218b8ad70 added attempt to resolve system scoped dependency with test cases 2017-05-14 07:45:55 -04:00
Jeremy Long
555b1dc1cc resolution for enhancement #729 2017-05-13 08:40:08 -04:00
Jeremy Long
523eed9319 resolved issue #686 - reports are generated even if no dependencies were analyzed 2017-05-13 08:38:43 -04:00
Jeremy Long
9c7f6daf75 updated groovy version to allow the use of newer APIs in the build scripts 2017-05-13 08:37:22 -04:00
Jeremy Long
f2037b3fab Merge pull request #723 from jeremylong/csv
Csv Report
2017-05-13 06:47:09 -04:00
Seth Jackson
c545285f7f Update Windows development usage.
So that the example invocation works in PowerShell and cmd.
2017-05-09 10:57:58 -04:00
Seth Jackson
290cd0507e Suppress EntityFramework false positives. 2017-05-09 10:32:41 -04:00
Jeremy Long
ee72f172d2 fix codacy issue 2017-05-08 21:41:05 -04:00
Jeremy Long
e721dac389 implemented CSV reports per #675 2017-05-08 07:43:39 -04:00
Jeremy Long
4c15993a44 updated documentation for issue #675 and pr #716 2017-05-08 07:42:01 -04:00
Jeremy Long
8fc42078c7 checkstyle corrections, minor restructuring, etc. 2017-05-07 18:40:25 -04:00
Jeremy Long
06d6fe4bd6 updated #716 2017-05-07 17:47:24 -04:00
Jeremy Long
96cda322a3 fixed coverity reported bug 2017-05-07 17:11:46 -04:00
Jeremy Long
0c991af58d fixed logging for #710 2017-05-07 16:52:20 -04:00
Jeremy Long
3677b5f429 Merge pull request #722 from jeremylong/falsepositives
Fix False Positives
2017-05-07 10:40:56 -04:00
Jeremy Long
fd0abd9066 updated test cases for FP 2017-05-07 10:14:50 -04:00
Jeremy Long
abb10600f7 fix for PR #716 - corrected malformed json generation 2017-05-07 10:14:09 -04:00
Jeremy Long
c9a6bb4b16 Merge pull request #721 from arno01/trivial
fix readme
2017-05-07 08:59:17 -04:00
Jeremy Long
9ff0042527 Merge branch 'master' into falsepositives 2017-05-07 08:59:16 -04:00
Andrey Arapov
0504f9c4cc fix readme 2017-05-07 10:07:28 +02:00
Jeremy Long
7b7861206b fixes for #700, #713, and #699 2017-05-06 19:25:54 -04:00
Jeremy Long
6f9207fe25 merged 2017-05-06 16:47:17 -04:00
Jeremy Long
de6cd3621b updated docker documentation 2017-05-06 16:44:04 -04:00
Jeremy Long
04b506662f Merge pull request #719 from hochzehn/improve-dockerfile
Improve dockerfile
2017-05-06 16:10:48 -04:00
Jeremy Long
c1250fc53e Merge branch 'ThomasGoeytil-json-support' 2017-05-06 15:13:06 -04:00
Jeremy Long
c2f521f528 updated to support changes from #682 2017-05-06 15:12:27 -04:00
Jeremy Long
5fde08b001 Merge branch 'json-support' of https://github.com/ThomasGoeytil/DependencyCheck into ThomasGoeytil-json-support 2017-05-06 14:51:30 -04:00
Jeremy Long
69d621b981 Merge pull request #720 from hochzehn/fix-cli-doc
Fix argument name for CLI.
2017-05-06 14:48:15 -04:00
Jeremy Long
4134fb3fef fixed sorting issue and resolved enhancement request #515 2017-05-06 12:05:30 -04:00
Jeremy Long
81b2b966ba added additional check to add proxy credentials 2017-05-06 10:48:31 -04:00
janpapenbrock
ae65ebe687 Fix argument name for CLI. 2017-05-06 11:11:13 +02:00
janpapenbrock
03f84fa77e Improve docker usage documentation. 2017-05-06 10:42:24 +02:00
janpapenbrock
ff6b3dbd4f Refactor to make URLs easier to change and reduce repetition. 2017-05-06 10:30:29 +02:00
janpapenbrock
bf7b8ccce8 Use specific user name to easily identify who is doing things here. 2017-05-06 10:20:02 +02:00
janpapenbrock
57b1895b5e Refactor user name into variable. 2017-05-06 10:19:27 +02:00
janpapenbrock
8edf65186f Clean up after download to reduce image size. 2017-05-06 10:06:48 +02:00
janpapenbrock
13d781d2b1 Re-order arguments in likeliness of being commented out. 2017-05-06 10:06:23 +02:00
janpapenbrock
7c1c99f5f9 Use script without arguments as entry point to allow running any command on the resulting container without having to override entry point. 2017-05-06 10:06:23 +02:00
janpapenbrock
0a02f43b8c Refactor Dockerfile for readability. 2017-05-06 10:06:22 +02:00
Jeremy Long
d4e50d9560 Merge pull request #717 from jeremylong/jacoco
Jacoco
2017-05-05 15:29:27 -04:00
Jeremy Long
5681e0bfdf fixed test cases 2017-05-05 15:17:39 -04:00
Jeremy Long
55bfe4cad8 Merge branch 'master' into jacoco 2017-05-05 14:41:27 -04:00
Jeremy Long
d726792be6 Merge branch 'Prakhash-Issues#665_implement' 2017-05-05 14:38:48 -04:00
Jeremy Long
5c21451760 updated to use the new schema 2017-05-05 14:15:21 -04:00
Jeremy Long
b3736ac13a updated template optional add the GAV 2017-05-05 14:15:04 -04:00
Jeremy Long
a4899de956 added new schema to support the addition of the GAV 2017-05-05 14:14:17 -04:00
Jeremy Long
e3ca70ba0d reverted changes in PR to old schemas 2017-05-05 14:13:35 -04:00
Jeremy Long
bdace1b1b7 Merge branch 'Issues#665_implement' of https://github.com/Prakhash/DependencyCheck into Prakhash-Issues#665_implement 2017-05-04 06:48:31 -04:00
Jeremy Long
567022a9b7 updated so that jacoco results can be sent to codacy 2017-05-03 06:28:30 -04:00
Thomas Gøytil
83262afd13 Added support to generate report in JSON format 2017-05-01 18:11:53 +02:00
Jeremy Long
3ff838a2cc Merge branch 'master' into jacoco 2017-04-30 17:20:23 -04:00
Jeremy Long
40b5c45ef6 Merge pull request #705 from jeremylong/issue690_threadsafe
PR #705 contains several bug fixes.
2017-04-30 17:16:12 -04:00
Jeremy Long
c9ee55863f fixed merge 2017-04-12 10:42:02 -04:00
Jeremy Long
c622ff2b19 converted to using jacoco for code coverage 2017-04-02 08:16:21 -04:00
Prakhash
2b04c6a7dd changed the coordinates according to the pom file details 2017-03-13 15:52:50 +05:30
70 changed files with 2254 additions and 830 deletions

View File

@@ -1,3 +1,13 @@
language: java
jdk: oraclejdk7
script: mvn install -DreleaseTesting
env:
global:
secure: ZUzhWfpXJw/oAeDlUkDFkEJMT0T7kCN3d7ah8urkL2B0KFfKOqQagkbXkgvDa1SYud8VdcnoGa69LfkEr5IrdqW7R4bEYZAiN5swm4Z0iO8t53szVspm2f+O9jQ44O/sfOfpfLxWUUuhdc7Vbrszp+tSszxdPmssWL+f5a/mfWs=
before_install:
- sudo apt-get install jq
- wget -O ~/codacy-coverage-reporter-assembly-latest.jar $(curl https://api.github.com/repos/codacy/codacy-coverage-reporter/releases/latest | jq -r .assets[0].browser_download_url)
after_success:
- java -cp ~/codacy-coverage-reporter-assembly-latest.jar com.codacy.CodacyCoverageReporter -l Java -r build-reporting/target/site/jacoco-aggregate/jacoco.xml

View File

@@ -2,13 +2,28 @@ FROM java:8
MAINTAINER Timo Pagel <dependencycheckmaintainer@timo-pagel.de>
RUN wget -O /tmp/current.txt http://jeremylong.github.io/DependencyCheck/current.txt && current=$(cat /tmp/current.txt) && wget https://dl.bintray.com/jeremy-long/owasp/dependency-check-$current-release.zip && unzip dependency-check-$current-release.zip && mv dependency-check /usr/share/
ENV user=dependencycheck
ENV version_url=https://jeremylong.github.io/DependencyCheck/current.txt
ENV download_url=https://dl.bintray.com/jeremy-long/owasp
RUN useradd -ms /bin/bash dockeruser && chown -R dockeruser:dockeruser /usr/share/dependency-check && mkdir /report && chown -R dockeruser:dockeruser /report
USER dockeruser
RUN wget -O /tmp/current.txt ${version_url} && \
version=$(cat /tmp/current.txt) && \
file="dependency-check-${version}-release.zip" && \
wget "$download_url/$file" && \
unzip ${file} && \
rm ${file} && \
mv dependency-check /usr/share/
VOLUME "/src /usr/share/dependency-check/data /report"
RUN useradd -ms /bin/bash ${user} && \
chown -R ${user}:${user} /usr/share/dependency-check && \
mkdir /report && \
chown -R ${user}:${user} /report
USER ${user}
VOLUME ["/src" "/usr/share/dependency-check/data" "/report"]
WORKDIR /report
ENTRYPOINT ["/usr/share/dependency-check/bin/dependency-check.sh", "--scan", "/src"]
CMD ["--help"]
ENTRYPOINT ["/usr/share/dependency-check/bin/dependency-check.sh"]

View File

@@ -29,8 +29,8 @@ $ ./bin/dependency-check.sh --project Testing --out . --scan [path to jar files
```
On Windows
```
> bin/dependency-check.bat -h
> bin/dependency-check.bat --project Testing --out . --scan [path to jar files to be scanned]
> .\bin\dependency-check.bat -h
> .\bin\dependency-check.bat --project Testing --out . --scan [path to jar files to be scanned]
```
On Mac with [Homebrew](http://brew.sh)
```
@@ -93,40 +93,46 @@ $ ./dependency-check-cli/target/release/bin/dependency-check.sh --project Testin
On Windows
```
> mvn install
> dependency-check-cli/target/release/bin/dependency-check.bat -h
> dependency-check-cli/target/release/bin/dependency-check.bat --project Testing --out . --scan ./src/test/resources
> .\dependency-check-cli\target\release\bin\dependency-check.bat -h
> .\dependency-check-cli\target\release\bin\dependency-check.bat --project Testing --out . --scan ./src/test/resources
```
Then load the resulting 'DependencyCheck-Report.html' into your favorite browser.
### Docker
In the following example it is assumed that the source to be checked is in the actual directory. A persistent data directory and a persistent report directory is used so that the container can be destroyed after running it to make sure that you use the newest version, always.
In the following example it is assumed that the source to be checked is in the current working directory. Persistent data and report directories are used, allowing you to destroy the container after running.
```
# After the first run, feel free to change the owner of the directories to the owner of the created files and the permissions to 744
DATA_DIRECTORY=$HOME/OWASP-Dependency-Check/data
REPORT_DIRECTORY=/$HOME/OWASP-Dependency-Check/reports
#!/bin/sh
if [ ! -d $DATA_DIRECTORY ]; then
echo "Initially creating persistent directories"
mkdir -p $DATA_DIRECTORY
chmod -R 777 $DATA_DIRECTORY
OWASPDC_DIRECTORY=$HOME/OWASP-Dependency-Check
DATA_DIRECTORY="$OWASPDC_DIRECTORY/data"
REPORT_DIRECTORY="$OWASPDC_DIRECTORY/reports"
mkdir -p $REPORT_DIRECTORY
chmod -R 777 $REPORT_DIRECTORY
if [ ! -d "$DATA_DIRECTORY" ]; then
echo "Initially creating persistent directories"
mkdir -p "$DATA_DIRECTORY"
chmod -R 777 "$DATA_DIRECTORY"
mkdir -p "$REPORT_DIRECTORY"
chmod -R 777 "$REPORT_DIRECTORY"
fi
docker pull owasp/dependency-check # Make sure it is the actual version
# Make sure we are using the latest version
docker pull owasp/dependency-check
docker run --rm \
--volume $(pwd):/src \
--volume $DATA_DIRECTORY:/usr/share/dependency-check/data \
--volume $REPORT_DIRECTORY:/report \
--name dependency-check \
dc \
--suppression "/src/security/dependency-check-suppression.xml"\
--format "ALL" \
--project "My OWASP Dependency Check Project" \
--volume $(pwd):/src \
--volume "$DATA_DIRECTORY":/usr/share/dependency-check/data \
--volume "$REPORT_DIRECTORY":/report \
owasp/dependency-check \
--scan /src \
--format "ALL" \
--project "My OWASP Dependency Check Project"
# Use suppression like this: (/src == $pwd)
# --suppression "/src/security/dependency-check-suppression.xml"
```

80
build-reporting/pom.xml Normal file
View File

@@ -0,0 +1,80 @@
<!--
This file is part of dependency-check build-reporting.
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.4.6-SNAPSHOT</version>
</parent>
<artifactId>build-reporting</artifactId>
<!-- begin copy from http://minds.coremedia.com/2012/09/11/problem-solved-deploy-multi-module-maven-project-site-as-github-pages/ -->
<distributionManagement>
<site>
<id>github-pages-site</id>
<name>Deployment through GitHub's site deployment plugin</name>
<url>${basedir}/../target/site/${project.version}/build-reporting</url>
</site>
</distributionManagement>
<!-- end copy -->
<dependencies>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-ant</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
About
=====
OWASP dependency-check build reporting is used to aggregate jacoco test coverage results
so that they can be posted to [Codacy](https://www.codacy.com/app/OWASP_Reviews/DependencyCheck/dashboard)
to track code coverage.

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
This file is part of dependency-check build reporting.
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.
-->
<project name="dependency-check-build-reporting">
<bannerLeft>
<name>OWASP dependency-check build reporting</name>
<alt>OWASP dependency-check build reporting</alt>
<src>../images/dc.svg</src>
</bannerLeft>
<body>
<breadcrumbs>
<item name="dependency-check" href="../index.html"/>
</breadcrumbs>
<menu ref="Project Documentation" />
<menu ref="reports" />
</body>
</project>

View File

@@ -223,48 +223,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/dependency-check-data</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<reporting>

View File

@@ -146,7 +146,7 @@ public class Check extends Update {
private boolean updateOnly = false;
/**
* The report format to be generated (HTML, XML, VULN, ALL). Default is
* The report format to be generated (HTML, XML, VULN, CSV, JSON, ALL). Default is
* HTML.
*/
private String reportFormat = "HTML";
@@ -940,16 +940,7 @@ public class Check extends Update {
throw new BuildException(ex);
}
}
DatabaseProperties prop = null;
try (CveDB cve = CveDB.getInstance()) {
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
//TODO shouldn't this be a fatal exception
log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
}
final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
reporter.generateReports(reportOutputDirectory, reportFormat);
engine.writeReports(getProjectName(),new File(reportOutputDirectory), reportFormat);
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
@@ -1102,7 +1093,7 @@ public class Check extends Update {
}
/**
* An enumeration of supported report formats: "ALL", "HTML", "XML", "VULN",
* An enumeration of supported report formats: "ALL", "HTML", "XML", "CSV", "JSON", "VULN",
* etc..
*/
public static class ReportFormats extends EnumeratedAttribute {

View File

@@ -36,11 +36,11 @@ cveValidForHours | Sets the number of hours to wait before checking for new
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
failOnError | Whether the build should fail if there is an error executing the dependency-check analysis | true
projectName | The name of the project being scanned. | Dependency-Check
reportFormat | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
reportFormat | The report format to be generated (HTML, XML, CSV, JSON, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) | &nbsp;
hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) | &nbsp;
proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html) | &nbsp;
proxyServer | The Proxy Server; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;

View File

@@ -69,62 +69,6 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<!--instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation-->
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>org.owasp.dependencycheck.App</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>cpe</name>
<value>data/cpe</value>
<workingDirectory>target</workingDirectory>
</property>
<property>
<name>cve</name>
<value>data/cpe</value>
<workingDirectory>target</workingDirectory>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>

View File

@@ -281,18 +281,9 @@ public class App {
}
exCol = ex;
}
final List<Dependency> dependencies = engine.getDependencies();
DatabaseProperties prop = null;
try (CveDB cve = CveDB.getInstance()) {
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
//TODO shouldn't this be a fatal exception
LOGGER.debug("Unable to retrieve DB Properties", ex);
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
engine.writeReports(applicationName, new File(reportDirectory), outputFormat);
} catch (ReportException ex) {
if (exCol != null) {
exCol.addException(ex);
@@ -306,7 +297,7 @@ public class App {
}
//Set the exit code based on whether we found a high enough vulnerability
for (Dependency dep : dependencies) {
for (Dependency dep : engine.getDependencies()) {
if (!dep.getVulnerabilities().isEmpty()) {
for (Vulnerability vuln : dep.getVulnerabilities()) {
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
@@ -316,7 +307,6 @@ public class App {
}
}
}
return retCode;
} finally {
if (engine != null) {
@@ -353,8 +343,7 @@ public class App {
* @throws InvalidSettingException thrown when a user defined properties
* file is unable to be loaded.
*/
private void populateSettings(CliParser cli) throws InvalidSettingException {
final boolean autoUpdate = cli.isAutoUpdate();
protected void populateSettings(CliParser cli) throws InvalidSettingException {
final String connectionTimeout = cli.getConnectionTimeout();
final String proxyServer = cli.getProxyServer();
final String proxyPort = cli.getProxyPort();
@@ -377,7 +366,8 @@ public class App {
final String cveBase12 = cli.getBaseCve12Url();
final String cveBase20 = cli.getBaseCve20Url();
final Integer cveValidForHours = cli.getCveValidForHours();
final boolean experimentalEnabled = cli.isExperimentalEnabled();
final Boolean autoUpdate = cli.isAutoUpdate();
final Boolean experimentalEnabled = cli.isExperimentalEnabled();
if (propertiesFile != null) {
try {
@@ -390,7 +380,7 @@ public class App {
}
// We have to wait until we've merged the properties before attempting to set whether we use
// the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
// on the command line
// on the command line. This is true of other boolean values set below not using the setBooleanIfNotNull.
final boolean nexusUsesProxy = cli.isNexusUsesProxy();
if (dataDirectory != null) {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
@@ -404,7 +394,7 @@ public class App {
final File dataDir = new File(base, sub);
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
}
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUser);
@@ -415,7 +405,8 @@ public class App {
Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
//File Type Analyzer Settings
Settings.setBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !cli.isJarDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !cli.isArchiveDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !cli.isPythonDistributionDisabled());

View File

@@ -120,7 +120,7 @@ public final class CliParser {
Format.valueOf(format);
} catch (IllegalArgumentException ex) {
final String msg = String.format("An invalid 'format' of '%s' was specified. "
+ "Supported output formats are XML, HTML, VULN, or ALL", format);
+ "Supported output formats are HTML, XML, CSV, JSON, VULN, or ALL", format);
throw new ParseException(msg);
}
}
@@ -262,7 +262,7 @@ public final class CliParser {
.build();
final Option outputFormat = Option.builder(ARGUMENT.OUTPUT_FORMAT_SHORT).argName("format").hasArg().longOpt(ARGUMENT.OUTPUT_FORMAT)
.desc("The output format to write to (XML, HTML, VULN, ALL). The default is HTML.")
.desc("The output format to write to (XML, JSON, HTML, VULN, ALL). The default is HTML.")
.build();
final Option verboseLog = Option.builder(ARGUMENT.VERBOSE_LOG_SHORT).argName("file").hasArg().longOpt(ARGUMENT.VERBOSE_LOG)
@@ -567,6 +567,32 @@ public final class CliParser {
return value;
}
/**
* Utility method to determine if one of the disable options has been set.
* If not set, this method will check the currently configured settings for
* the current value to return.
*
* Example given `--disableArchive` on the command line would cause this
* method to return true for the disable archive setting.
*
* @param argument the command line argument
* @param setting the corresponding settings key
* @return true if the disable option was set, if not set the currently
* configured value will be returned
*/
private boolean hasDisableOption(String argument, String setting) {
if (line == null || !line.hasOption(argument)) {
try {
return !Settings.getBoolean(setting);
} catch (InvalidSettingException ise) {
LOGGER.warn("Invalid property setting '{}' defaulting to false", setting);
return false;
}
} else {
return true;
}
}
/**
* Returns true if the disableJar command line argument was specified.
*
@@ -574,7 +600,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isJarDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_JAR);
return hasDisableOption(ARGUMENT.DISABLE_JAR, Settings.KEYS.ANALYZER_JAR_ENABLED);
}
/**
@@ -584,7 +610,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isArchiveDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ARCHIVE);
return hasDisableOption(ARGUMENT.DISABLE_ARCHIVE, Settings.KEYS.ANALYZER_ARCHIVE_ENABLED);
}
/**
@@ -594,7 +620,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNuspecDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NUSPEC);
return hasDisableOption(ARGUMENT.DISABLE_NUSPEC, Settings.KEYS.ANALYZER_NUSPEC_ENABLED);
}
/**
@@ -604,7 +630,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isAssemblyDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_ASSEMBLY);
return hasDisableOption(ARGUMENT.DISABLE_ASSEMBLY, Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED);
}
/**
@@ -615,7 +641,7 @@ public final class CliParser {
* specified; otherwise false
*/
public boolean isBundleAuditDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_BUNDLE_AUDIT);
return hasDisableOption(ARGUMENT.DISABLE_BUNDLE_AUDIT, Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED);
}
/**
@@ -625,7 +651,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isPythonDistributionDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_DIST);
return hasDisableOption(ARGUMENT.DISABLE_PY_DIST, Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED);
}
/**
@@ -635,7 +661,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isPythonPackageDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_PY_PKG);
return hasDisableOption(ARGUMENT.DISABLE_PY_PKG, Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED);
}
/**
@@ -645,7 +671,7 @@ public final class CliParser {
* argument was specified; otherwise false
*/
public boolean isRubyGemspecDisabled() {
return (null != line) && line.hasOption(ARGUMENT.DISABLE_RUBYGEMS);
return hasDisableOption(ARGUMENT.DISABLE_RUBYGEMS, Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED);
}
/**
@@ -655,7 +681,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isCmakeDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CMAKE);
return hasDisableOption(ARGUMENT.DISABLE_CMAKE, Settings.KEYS.ANALYZER_CMAKE_ENABLED);
}
/**
@@ -665,7 +691,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isAutoconfDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_AUTOCONF);
return hasDisableOption(ARGUMENT.DISABLE_AUTOCONF, Settings.KEYS.ANALYZER_AUTOCONF_ENABLED);
}
/**
@@ -675,7 +701,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isComposerDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_COMPOSER);
return hasDisableOption(ARGUMENT.DISABLE_COMPOSER, Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED);
}
/**
@@ -685,7 +711,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNexusDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
return hasDisableOption(ARGUMENT.DISABLE_NEXUS, Settings.KEYS.ANALYZER_NEXUS_ENABLED);
}
/**
@@ -695,7 +721,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isOpenSSLDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_OPENSSL);
return hasDisableOption(ARGUMENT.DISABLE_OPENSSL, Settings.KEYS.ANALYZER_OPENSSL_ENABLED);
}
/**
@@ -705,7 +731,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isNodeJsDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NODE_JS);
return hasDisableOption(ARGUMENT.DISABLE_NODE_JS, Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED);
}
/**
@@ -716,7 +742,7 @@ public final class CliParser {
* specified; otherwise false
*/
public boolean isCocoapodsAnalyzerDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_COCOAPODS);
return hasDisableOption(ARGUMENT.DISABLE_COCOAPODS, Settings.KEYS.ANALYZER_COCOAPODS_ENABLED);
}
/**
@@ -727,7 +753,7 @@ public final class CliParser {
* argument was specified; otherwise false
*/
public boolean isSwiftPackageAnalyzerDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_SWIFT);
return hasDisableOption(ARGUMENT.DISABLE_SWIFT, Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED);
}
/**
@@ -737,7 +763,7 @@ public final class CliParser {
* otherwise false
*/
public boolean isCentralDisabled() {
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
return hasDisableOption(ARGUMENT.DISABLE_CENTRAL, Settings.KEYS.ANALYZER_CENTRAL_ENABLED);
}
/**
@@ -1029,10 +1055,10 @@ public final class CliParser {
* disabled via the command line this will return false.
*
* @return <code>true</code> if auto-update is allowed; otherwise
* <code>false</code>
* <code>null</code>
*/
public boolean isAutoUpdate() {
return line != null && !line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE);
public Boolean isAutoUpdate() {
return (line != null && line.hasOption(ARGUMENT.DISABLE_AUTO_UPDATE)) ? false : null;
}
/**
@@ -1134,10 +1160,10 @@ public final class CliParser {
/**
* Returns true if the experimental analyzers are enabled.
*
* @return true if the experimental analyzers are enabled; otherwise false
* @return true if the experimental analyzers are enabled; otherwise null
*/
public boolean isExperimentalEnabled() {
return line.hasOption(ARGUMENT.EXPERIMENTAL);
public Boolean isExperimentalEnabled() {
return (line != null && line.hasOption(ARGUMENT.EXPERIMENTAL)) ? true : null;
}
/**

View File

@@ -4,22 +4,22 @@ Command Line Arguments
The following table lists the command line arguments:
Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requirement
-------|-----------------------|-----------------|-------------|------------
| \-\-project | \<name\> | The name of the project being scanned. | Required
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. directory/**/*.jar). | Required
| \-\-exclude | \<pattern\> | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**). | Optional
| \-\-symLink | \<depth\> | The depth that symbolic links will be followed; the default is 0 meaning symbolic links will not be followed. | Optional
\-o | \-\-out | \<path\> | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, VULN, ALL). The default is HTML. | Required
| \-\-failOnCvss | \<score\> | If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified. | Optional
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
| \-\-suppression | \<file\> | The file path to the suppression XML file; used to suppress [false positives](../general/suppression.html). | Optional
\-h | \-\-help | | Print the help message. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | Optional
| \-\-cveValidForHours | \<hours\> | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | Optional
| \-\-experimental | | Enable the [experimental analyzers](../analyzers/index.html). If not set the analyzers marked as experimental below will not be loaded or used. | Optional
-------|------------------------|-----------------|-------------|------------
| \-\-project | \<name\> | The name of the project being scanned. | Required
\-s | \-\-scan | \<path\> | The path to scan \- this option can be specified multiple times. It is also possible to specify Ant style paths (e.g. directory/**/*.jar). | Required
| \-\-exclude | \<pattern\> | The path patterns to exclude from the scan \- this option can be specified multiple times. This accepts Ant style path patterns (e.g. **/exclude/**). | Optional
| \-\-symLink | \<depth\> | The depth that symbolic links will be followed; the default is 0 meaning symbolic links will not be followed. | Optional
\-o | \-\-out | \<path\> | The folder to write reports to. This defaults to the current directory. If the format is not set to ALL one could specify a specific file name. | Optional
\-f | \-\-format | \<format\> | The output format to write to (XML, HTML, CSV, JSON, VULN, ALL). The default is HTML. | Required
| \-\-failOnCvss | \<score\> | If the score set between 0 and 10 the exit code from dependency-check will indicate if a vulnerability with a CVSS score equal to or higher was identified. | Optional
\-l | \-\-log | \<file\> | The file path to write verbose logging information. | Optional
\-n | \-\-noupdate | | Disables the automatic updating of the CPE data. | Optional
| \-\-suppression | \<file\> | The file path to the suppression XML file; used to suppress [false positives](../general/suppression.html). | Optional
\-h | \-\-help | | Print the help message. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | Optional
| \-\-cveValidForHours | \<hours\> | The number of hours to wait before checking for new updates from the NVD. The default is 4 hours. | Optional
| \-\-enableExperimental | | Enable the [experimental analyzers](../analyzers/index.html). If not set the analyzers marked as experimental below will not be loaded or used. | Optional
Advanced Options
================

View File

@@ -13,18 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2015 The OWASP Foundatio. All Rights Reserved.
* Copyright (c) 2017 The OWASP Foundatio. All Rights Reserved.
*/
package org.owasp.dependencycheck;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author jeremy
*/
public class AppTest {
/**
* Test of ensureCanonicalPath method, of class App.
*/
@@ -35,17 +45,83 @@ public class AppTest {
String result = instance.ensureCanonicalPath(file);
assertFalse(result.contains(".."));
assertTrue(result.endsWith("*.jar"));
}
/**
* Test of ensureCanonicalPath method, of class App.
*/
@Test
public void testEnsureCanonicalPath2() {
String file = "../some/skip/../path/file.txt";
App instance = new App();
file = "../some/skip/../path/file.txt";
String expResult = "/some/path/file.txt";
String result = instance.ensureCanonicalPath(file);
result = instance.ensureCanonicalPath(file);
assertTrue("result=" + result, result.endsWith(expResult));
}
@Test(expected = UnrecognizedOptionException.class)
public void testPopulateSettingsException() throws FileNotFoundException, ParseException, InvalidSettingException, URISyntaxException {
String[] args = {"-invalidPROPERTY"};
assertTrue(testBooleanProperties(args, null));
}
@Test
public void testPopulateSettings() throws FileNotFoundException, ParseException, InvalidSettingException, URISyntaxException {
File prop = new File(this.getClass().getClassLoader().getResource("sample.properties").toURI().getPath());
String[] args = {"-P", prop.getAbsolutePath()};
Map<String, Boolean> expected = new HashMap<>();
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
assertTrue(testBooleanProperties(args, expected));
String[] args2 = {"-n"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
assertTrue(testBooleanProperties(args2, expected));
String[] args3 = {"-h"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.TRUE);
assertTrue(testBooleanProperties(args3, expected));
String[] args4 = {"--disableArchive"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
assertTrue(testBooleanProperties(args4, expected));
String[] args5 = {"-P", prop.getAbsolutePath(), "--disableArchive"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
assertTrue(testBooleanProperties(args5, expected));
prop = new File(this.getClass().getClassLoader().getResource("sample2.properties").toURI().getPath());
String[] args6 = {"-P", prop.getAbsolutePath(), "--disableArchive"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.TRUE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
assertTrue(testBooleanProperties(args6, expected));
String[] args7 = {"-P", prop.getAbsolutePath(), "--noupdate"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
assertTrue(testBooleanProperties(args7, expected));
String[] args8 = {"-P", prop.getAbsolutePath(), "--noupdate", "--disableArchive"};
expected.put(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE);
expected.put(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, Boolean.FALSE);
assertTrue(testBooleanProperties(args8, expected));
}
private boolean testBooleanProperties(String[] args, Map<String, Boolean> expected) throws URISyntaxException, FileNotFoundException, ParseException, InvalidSettingException {
Settings.initialize();
try {
final CliParser cli = new CliParser();
cli.parse(args);
App instance = new App();
instance.populateSettings(cli);
boolean results = true;
for (Map.Entry<String, Boolean> entry : expected.entrySet()) {
results &= Settings.getBoolean(entry.getKey()) == entry.getValue();
}
return results;
} finally {
Settings.cleanup();
}
}
}

View File

@@ -0,0 +1,33 @@
autoupdate=false
analyzer.experimental.enabled=false
analyzer.jar.enabled=true
analyzer.archive.enabled=true
analyzer.node.package.enabled=true
analyzer.composer.lock.enabled=true
analyzer.python.distribution.enabled=true
analyzer.python.package.enabled=true
analyzer.ruby.gemspec.enabled=true
analyzer.autoconf.enabled=true
analyzer.cmake.enabled=true
analyzer.assembly.enabled=true
analyzer.nuspec.enabled=true
analyzer.openssl.enabled=true
analyzer.central.enabled=true
analyzer.nexus.enabled=false
analyzer.cocoapods.enabled=true
analyzer.swift.package.manager.enabled=true
#whether the nexus analyzer uses the proxy
analyzer.nexus.proxy=true
analyzer.cpe.enabled=true
analyzer.cpesuppression.enabled=true
analyzer.dependencybundling.enabled=true
analyzer.dependencymerging.enabled=true
analyzer.falsepositive.enabled=true
analyzer.filename.enabled=true
analyzer.hint.enabled=true
analyzer.nvdcve.enabled=true
analyzer.vulnerabilitysuppression.enabled=true
updater.nvdcve.enabled=true
updater.versioncheck.enabled=true
analyzer.versionfilter.enabled=true

View File

@@ -0,0 +1,33 @@
autoupdate=true
analyzer.experimental.enabled=true
analyzer.jar.enabled=false
analyzer.archive.enabled=false
analyzer.node.package.enabled=false
analyzer.composer.lock.enabled=false
analyzer.python.distribution.enabled=false
analyzer.python.package.enabled=false
analyzer.ruby.gemspec.enabled=false
analyzer.autoconf.enabled=false
analyzer.cmake.enabled=false
analyzer.assembly.enabled=false
analyzer.nuspec.enabled=false
analyzer.openssl.enabled=false
analyzer.central.enabled=false
analyzer.nexus.enabled=true
analyzer.cocoapods.enabled=false
analyzer.swift.package.manager.enabled=false
#whether the nexus analyzer uses the proxy
analyzer.nexus.proxy=false
analyzer.cpe.enabled=false
analyzer.cpesuppression.enabled=false
analyzer.dependencybundling.enabled=false
analyzer.dependencymerging.enabled=false
analyzer.falsepositive.enabled=false
analyzer.filename.enabled=false
analyzer.hint.enabled=false
analyzer.nvdcve.enabled=false
analyzer.vulnerabilitysuppression.enabled=false
updater.nvdcve.enabled=false
updater.versioncheck.enabled=false
analyzer.versionfilter.enabled=false

View File

@@ -121,93 +121,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<instrumentation>
<!--ignoreTrivial>true</ignoreTrivial-->
<ignores>
<ignore>.*\$KEYS\.class</ignore>
<ignore>.*\$Element\.class</ignore>
</ignores>
<excludes>
<exclude>.*\$KEYS\.class</exclude>
<exclude>.*\$Element\.class</exclude>
</excludes>
</instrumentation>
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>org.owasp.dependencycheck.data.cpe.Fields</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>org.owasp.dependencycheck.App</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*MySQLTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
@@ -340,6 +253,10 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<groupId>com.sun.mail</groupId>
<artifactId>mailapi</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- The following dependencies are only used during testing -->
<dependency>
<groupId>org.apache.maven.scm</groupId>
@@ -470,6 +387,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -481,13 +399,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
@@ -507,7 +418,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</property>
</systemProperties>
<includes>
<include>**/*MySQLTest.java</include>
<include>**/*MySqlIT.java</include>
</includes>
</configuration>
<executions>
@@ -538,13 +449,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
@@ -564,7 +468,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</property>
</systemProperties>
<includes>
<include>**/*MySQLTest.java</include>
<include>**/*MySqlIT.java</include>
</includes>
</configuration>
<executions>
@@ -672,13 +576,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.gerrit</groupId>
<artifactId>gerrit-extension-api</artifactId>

View File

@@ -54,6 +54,9 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.reporting.ReportGenerator;
/**
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
@@ -796,4 +799,42 @@ public class Engine implements FileFilter {
exceptions.add(throwable);
throw new ExceptionCollection(message, exceptions, true);
}
/**
* Writes the report to the given output directory.
*
* @param applicationName the name of the application/project
* @param groupId the Maven groupId
* @param artifactId the Maven artifactId
* @param version the Maven version
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
* @param format the report format (ALL, HTML, CSV, JSON, etc.)
* @throws ReportException thrown if there is an error generating the report
*/
public void writeReports(String applicationName, String groupId, String artifactId,
String version, File outputDir, String format) throws ReportException {
DatabaseProperties prop = database.getDatabaseProperties();
final ReportGenerator r = new ReportGenerator(applicationName, groupId, artifactId, version, dependencies, getAnalyzers(), prop);
try {
r.write(outputDir.getAbsolutePath(), format);
} catch (ReportException ex) {
final String msg = String.format("Error generating the report for %s", applicationName);
throw new ReportException(msg, ex);
}
}
/**
* Writes the report to the given output directory.
*
* @param applicationName the name of the application/project
* @param outputDir the path to the output directory (can include the full
* file name if the format is not ALL)
* @param format the report format (ALL, HTML, CSV, JSON, etc.)
* @throws ReportException thrown if there is an error generating the report
*/
public void writeReports(String applicationName, File outputDir, String format) throws ReportException {
writeReports(applicationName, null, null, null, outputDir, format);
}
}

View File

@@ -840,21 +840,15 @@ public class DependencyCheckScanAgent {
*
* @param engine a dependency-check engine
* @param outDirectory the directory to write the reports to
* @throw ScanAgentException thrown if there is an error generating the
* report
*/
private void generateExternalReports(Engine engine, File outDirectory) {
DatabaseProperties prop = null;
try (CveDB cve = CveDB.getInstance()) {
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
//TODO shouldn't this be a fatal exception
LOGGER.debug("Unable to retrieve DB Properties", ex);
}
final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
private void generateExternalReports(Engine engine, File outDirectory) throws ScanAgentException {
try {
r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
} catch (IOException | ReportException ex) {
LOGGER.error("Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.debug("", ex);
engine.writeReports(applicationName, outDirectory, this.reportFormat.name());
} catch (ReportException ex) {
LOGGER.debug("Unexpected exception occurred during analysis; please see the verbose error log for more details.", ex);
throw new ScanAgentException("Error generating the report", ex);
}
}

View File

@@ -230,6 +230,16 @@ public final class CveDB implements AutoCloseable {
}
}
/**
* Method added for testing, returns the current usage count of the CveDB
* singleton.
*
* @return the current usage of the CveDB singleton
*/
protected synchronized int getUsageCount() {
return usageCount;
}
/**
* Opens the database connection. If the database does not exist, it will
* create a new one.

View File

@@ -182,8 +182,8 @@ public class NvdCveUpdater implements CachedWebDataSource {
LOGGER.trace("Ignorable exception", ex);
}
}
if (lockFile != null) {
lockFile.delete();
if (lockFile != null && lockFile.isFile() && !lockFile.delete()) {
LOGGER.error("Lock file '{}' was unable to be deleted. Please manually delete this file.", lockFile.toString());
}
}
}

View File

@@ -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);
}
}

View File

@@ -19,13 +19,16 @@ package org.owasp.dependencycheck.reporting;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Set;
import org.apache.commons.lang3.StringEscapeUtils;
import org.owasp.dependencycheck.dependency.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An extremely simple wrapper around various escape utils to perform URL and HTML encoding within the reports. This class was
* created to simplify the velocity configuration and avoid using the "built-in" escape tool.
* An extremely simple wrapper around various escape utils to perform URL and
* HTML encoding within the reports. This class was created to simplify the
* velocity configuration and avoid using the "built-in" escape tool.
*
* @author Jeremy Long
*/
@@ -80,4 +83,84 @@ public class EscapeTool {
}
return StringEscapeUtils.escapeXml11(text);
}
/**
* JSON Encodes the provided text.
*
* @param text the text to encode
* @return the JSON encoded text
*/
public String json(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return StringEscapeUtils.escapeJson(text);
}
/**
* Formats text for CSV format. This includes trimming whitespace, replace
* line breaks with spaces, and if necessary quotes the text and/or escapes
* contained quotes.
*
* @param text the text to escape and quote
* @return the escaped and quoted text
*/
public String csv(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return StringEscapeUtils.escapeCsv(text.trim().replace("\n", " "));
}
/**
* Takes a set of Identifiers, filters them to none CPE, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of none CPE identifiers
*/
public String csvIdentifiers(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if (!"cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
/**
* Takes a set of Identifiers, filters them to just CPEs, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of CPE identifiers
*/
public String csvCpe(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if ("cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
}

View File

@@ -17,17 +17,16 @@
*/
package org.owasp.dependencycheck.reporting;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.*;
import java.util.List;
import com.google.gson.JsonSyntaxException;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import static com.google.gson.stream.JsonToken.*;
import com.google.gson.stream.JsonWriter;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
@@ -78,7 +77,15 @@ public class ReportGenerator {
/**
* Generate HTML Vulnerability report.
*/
VULN
VULN,
/**
* Generate JSON report.
*/
JSON,
/**
* Generate CSV report.
*/
CSV
}
/**
* The Velocity Engine.
@@ -100,29 +107,35 @@ public class ReportGenerator {
*/
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
velocityEngine = createVelocityEngine();
context = createContext();
velocityEngine.init();
final EscapeTool enc = new EscapeTool();
context = createContext(applicationName, dependencies, analyzers, properties);
}
final DateTime dt = new DateTime();
final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
/**
* Constructs a new ReportGenerator.
*
* @param applicationName the application name being analyzed
* @param groupID the group id of the project being analyzed
* @param artifactID the application id of the project being analyzed
* @param version the application version of the project being analyzed
* @param dependencies the list of dependencies
* @param analyzers the list of analyzers used
* @param properties the database properties (containing timestamps of the
* NVD CVE data)
*/
public ReportGenerator(String applicationName, String groupID, String artifactID, String version,
List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
// final Date d = new Date();
// final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
// final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
final String scanDate = dateFormat.print(dt);
final String scanDateXML = dateFormatXML.print(dt);
context.put("applicationName", applicationName);
context.put("dependencies", dependencies);
context.put("analyzers", analyzers);
context.put("properties", properties);
context.put("scanDate", scanDate);
context.put("scanDateXML", scanDateXML);
context.put("enc", enc);
context.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
this(applicationName, dependencies, analyzers, properties);
if (version != null) {
context.put("applicationVersion", version);
}
if (artifactID != null) {
context.put("artifactID", artifactID);
}
if (groupID != null) {
context.put("groupID", groupID);
}
}
/**
@@ -138,94 +151,162 @@ public class ReportGenerator {
}
/**
* Creates a new Velocity Context.
* Constructs the velocity context used to generate the dependency-check
* reports.
*
* @return a Velocity Context
* @param applicationName the application name being analyzed
* @param dependencies the list of dependencies
* @param analyzers the list of analyzers used
* @param properties the database properties (containing timestamps of the
* NVD CVE data)
* @return the velocity context
*/
private Context createContext() {
return new VelocityContext();
private VelocityContext createContext(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
final DateTime dt = new DateTime();
final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
final String scanDate = dateFormat.print(dt);
final String scanDateXML = dateFormatXML.print(dt);
VelocityContext ctxt = new VelocityContext();
ctxt.put("applicationName", applicationName);
ctxt.put("dependencies", dependencies);
ctxt.put("analyzers", analyzers);
ctxt.put("properties", properties);
ctxt.put("scanDate", scanDate);
ctxt.put("scanDateXML", scanDateXML);
ctxt.put("enc", new EscapeTool());
ctxt.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
return ctxt;
}
/**
* Generates the Dependency Reports for the identified dependencies.
* Writes the dependency-check report to the given output location.
*
* @param outputStream the OutputStream to send the generated report to
* @param format the format the report should be written in
* @throws IOException is thrown when the template file does not exist
* @throws Exception is thrown if there is an error writing out the reports
*/
public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
if (format == Format.XML || format == Format.ALL) {
generateReport("XmlReport", outputStream);
}
if (format == Format.HTML || format == Format.ALL) {
generateReport("HtmlReport", outputStream);
}
if (format == Format.VULN || format == Format.ALL) {
generateReport("VulnerabilityReport", outputStream);
}
}
/**
* Generates the Dependency Reports for the identified dependencies.
*
* @param outputDir the path where the reports should be written
* @param format the format the report should be written in
* @throws ReportException is thrown if there is an error writing out the
* reports
*/
public void generateReports(String outputDir, Format format) throws ReportException {
if (format == Format.XML || format == Format.ALL) {
generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
}
if (format == Format.HTML || format == Format.ALL) {
generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
}
if (format == Format.VULN || format == Format.ALL) {
generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html");
}
}
/**
* Generates the Dependency Reports for the identified dependencies.
*
* @param outputDir the path where the reports should be written
* @param outputFormat the format the report should be written in (XML,
* HTML, ALL)
* @param outputLocation the path where the reports should be written
* @param format the format the report should be written in (XML, HTML,
* JSON, CSV, ALL) or even the path to a custom velocity template (either
* fully qualified or the template name on the class path).
* @throws ReportException is thrown if there is an error creating out the
* reports
*/
public void generateReports(String outputDir, String outputFormat) throws ReportException {
final String format = outputFormat.toUpperCase();
final String pathToCheck = outputDir.toLowerCase();
if (format.matches("^(XML|HTML|VULN|ALL)$")) {
if ("XML".equalsIgnoreCase(format)) {
if (pathToCheck.endsWith(".xml")) {
generateReport("XmlReport", outputDir);
} else {
generateReports(outputDir, Format.XML);
public void write(String outputLocation, String format) throws ReportException {
Format reportFormat = null;
try {
reportFormat = Format.valueOf(format.toUpperCase());
} catch (IllegalArgumentException ex) {
LOGGER.trace("ignore this exception", ex);
}
if (reportFormat != null) {
write(outputLocation, reportFormat);
} else {
File out = getReportFile(outputLocation, null);
if (out.isDirectory()) {
throw new ReportException("Unable to write non-standard VSL output to a directory, please specify a file name");
}
processTemplate(format, out);
}
}
/**
* Writes the dependency-check report(s).
*
* @param outputLocation the path where the reports should be written
* @param format the format the report should be written in (XML, HTML, ALL)
* @throws ReportException is thrown if there is an error creating out the
* reports
*/
public void write(String outputLocation, Format format) throws ReportException {
if (format == Format.ALL) {
for (Format f : Format.values()) {
if (f != Format.ALL) {
write(outputLocation, f);
}
}
if ("HTML".equalsIgnoreCase(format)) {
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
generateReport("HtmlReport", outputDir);
} else {
generateReports(outputDir, Format.HTML);
}
}
if ("VULN".equalsIgnoreCase(format)) {
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
generateReport("VulnReport", outputDir);
} else {
generateReports(outputDir, Format.VULN);
}
}
if ("ALL".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.ALL);
} else {
final File out = getReportFile(outputLocation, format);
final String templateName = format.toString().toLowerCase() + "Report";
processTemplate(templateName, out);
if (format == Format.JSON) {
pretifyJson(out.getPath());
}
}
}
// /**
// * Writes the dependency-check report(s).
// *
// * @param outputStream the OutputStream to send the generated report to
// * @param format the format the report should be written in
// * @throws ReportException thrown if the report format is ALL
// * @throws IOException is thrown when the template file does not exist
// * @throws Exception is thrown if there is an error writing out the reports
// */
// public void write(OutputStream outputStream, Format format) throws ReportException, IOException, Exception {
// if (format == Format.ALL) {
// throw new ReportException("Unable to write ALL reports to a single output stream, please check the API");
// }
// final String templateName = format.toString().toLowerCase() + "Report";
// processTemplate(templateName, outputStream);
// }
/**
* Determines the report file name based on the give output location and
* format. If the output location contains a full file name that has the
* correct extension for the given report type then the output location is
* returned. However, if the output location is a directory, this method
* will generate the correct name for the given output format.
*
* @param outputLocation the specified output location
* @param format the report format
* @return the report File
*/
protected File getReportFile(String outputLocation, Format format) {
File outFile = new File(outputLocation);
if (outFile.getParentFile() == null) {
outFile = new File(".", outputLocation);
}
final String pathToCheck = outputLocation.toLowerCase();
if (format == Format.XML && !pathToCheck.endsWith(".xml")) {
return new File(outFile, "dependency-check-report.xml");
}
if (format == Format.HTML && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
return new File(outFile, "dependency-check-report.html");
}
if (format == Format.VULN && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
return new File(outFile, "dependency-check-vulnerability.html");
}
if (format == Format.JSON && !pathToCheck.endsWith(".json")) {
return new File(outFile, "dependency-check-report.json");
}
if (format == Format.CSV && !pathToCheck.endsWith(".csv")) {
return new File(outFile, "dependency-check-report.csv");
}
return outFile;
}
/**
* Generates a report from a given Velocity Template. The template name
* provided can be the name of a template contained in the jar file, such as
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
* template file.
*
* @param template the name of the template to load
* @param file the output file to write the report to
* @throws ReportException is thrown when the report cannot be generated
*/
protected void processTemplate(String template, File file) throws ReportException {
ensureParentDirectoryExists(file);
try (OutputStream output = new FileOutputStream(file)) {
processTemplate(template, output);
} catch (IOException ex) {
throw new ReportException(String.format("Unable to write to file: %s", file), ex);
}
}
/**
* Generates a report from a given Velocity Template. The template name
* provided can be the name of a template contained in the jar file, such as
@@ -236,29 +317,33 @@ public class ReportGenerator {
* @param outputStream the OutputStream to write the report to
* @throws ReportException is thrown when an exception occurs
*/
protected void generateReport(String templateName, OutputStream outputStream) throws ReportException {
protected void processTemplate(String templateName, OutputStream outputStream) throws ReportException {
InputStream input = null;
String templatePath = null;
String logTag = null;
final File f = new File(templateName);
try {
if (f.exists() && f.isFile()) {
if (f.isFile()) {
try {
templatePath = templateName;
logTag = templateName;
input = new FileInputStream(f);
} catch (FileNotFoundException ex) {
throw new ReportException("Unable to locate template file: " + templateName, ex);
}
} else {
templatePath = "templates/" + templateName + ".vsl";
input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
logTag = "templates/" + templateName + ".vsl";
input = this.getClass().getClassLoader().getResourceAsStream(logTag);
}
if (input == null) {
throw new ReportException("Template file doesn't exist: " + templatePath);
logTag = templateName;
input = this.getClass().getClassLoader().getResourceAsStream(templateName);
}
if (input == null) {
throw new ReportException("Template file doesn't exist: " + logTag);
}
try (InputStreamReader reader = new InputStreamReader(input, "UTF-8");
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8")) {
if (!velocityEngine.evaluate(context, writer, templatePath, reader)) {
if (!velocityEngine.evaluate(context, writer, logTag, reader)) {
throw new ReportException("Failed to convert the template into html.");
}
writer.flush();
@@ -277,32 +362,106 @@ public class ReportGenerator {
}
}
}
/**
* Generates a report from a given Velocity Template. The template name
* provided can be the name of a template contained in the jar file, such as
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
* template file.
* Validates that the given file's parent directory exists. If the directory
* does not exist an attempt to create the necessary path is made; if that
* fails a ReportException will be raised.
*
* @param templateName the name of the template to load
* @param outFileName the filename and path to write the report to
* @throws ReportException is thrown when the report cannot be generated
* @param file the file or directory directory
* @throws ReportException thrown if the parent directory does not exist and
* cannot be created
*/
protected void generateReport(String templateName, String outFileName) throws ReportException {
File outFile = new File(outFileName);
if (outFile.getParentFile() == null) {
outFile = new File(".", outFileName);
}
if (!outFile.getParentFile().exists()) {
final boolean created = outFile.getParentFile().mkdirs();
private void ensureParentDirectoryExists(File file) throws ReportException {
if (!file.getParentFile().exists()) {
final boolean created = file.getParentFile().mkdirs();
if (!created) {
throw new ReportException("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
final String msg = String.format("Unable to create directory '%s'.", file.getParentFile().getAbsolutePath());
throw new ReportException(msg);
}
}
try (OutputStream outputSteam = new FileOutputStream(outFile)) {
generateReport(templateName, outputSteam);
}
/**
* Reformats the given JSON file.
*
* @param pathToJson the path to the JSON file to be reformatted
* @throws JsonSyntaxException thrown if the given JSON file is malformed
*/
private void pretifyJson(String pathToJson) throws JsonSyntaxException {
final String outputPath = pathToJson + ".pretty";
final File in = new File(pathToJson);
final File out = new File(outputPath);
try (JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream(in), StandardCharsets.UTF_8));
JsonWriter writer = new JsonWriter(new OutputStreamWriter(new FileOutputStream(out), StandardCharsets.UTF_8))) {
prettyPrint(reader, writer);
} catch (IOException ex) {
throw new ReportException("Unable to write to file: " + outFile, ex);
LOGGER.error("Unable to generate pretty report, caused by: ", ex.getMessage());
return;
}
if (out.isFile() && in.isFile() && in.delete()) {
try {
org.apache.commons.io.FileUtils.moveFile(out, in);
} catch (IOException ex) {
LOGGER.error("Unable to generate pretty report, caused by: ", ex.getMessage());
}
}
}
/**
* Streams from a json reader to a json writer and performs pretty printing.
*
* This function is copied from https://sites.google.com/site/gson/streaming
*
* @param reader json reader
* @param writer json writer
* @throws IOException thrown if the json is malformed
*/
private static void prettyPrint(JsonReader reader, JsonWriter writer) throws IOException {
writer.setIndent(" ");
while (true) {
final JsonToken token = reader.peek();
switch (token) {
case BEGIN_ARRAY:
reader.beginArray();
writer.beginArray();
break;
case END_ARRAY:
reader.endArray();
writer.endArray();
break;
case BEGIN_OBJECT:
reader.beginObject();
writer.beginObject();
break;
case END_OBJECT:
reader.endObject();
writer.endObject();
break;
case NAME:
final String name = reader.nextName();
writer.name(name);
break;
case STRING:
final String s = reader.nextString();
writer.value(s);
break;
case NUMBER:
final String n = reader.nextString();
writer.value(new BigDecimal(n));
break;
case BOOLEAN:
final boolean b = reader.nextBoolean();
writer.value(b);
break;
case NULL:
reader.nextNull();
writer.nullValue();
break;
case END_DOCUMENT:
return;
default:
LOGGER.debug("Unexpected JSON toekn {}", token.toString());
break;
}
}
}
}

View File

@@ -62,7 +62,7 @@ public class PomParser {
return parse(fis);
} catch (IOException ex) {
LOGGER.debug("", ex);
throw new PomParseException(ex);
throw new PomParseException(String.format("Unable to parse pom '%s'", file.toString()), ex);
}
}

View File

@@ -1,5 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.1.xsd">
<suppress base="true">
<notes><![CDATA[
This suppresses false positives for Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll.
]]></notes>
<filePath regex="true">.*Microsoft\.VisualStudio\.QualityTools\.UnitTestFramework*\.dll</filePath>
<cve>CVE-2014-3802</cve>
</suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses false positives for EntityFramework.SqlServer.dll.
]]></notes>
<filePath regex="true">.*EntityFramework\.SqlServer*\.dll</filePath>
<cpe>cpe:/a:microsoft:server:6.0.0.0</cpe>
<cpe>cpe:/a:microsoft:sql_server:6.0</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
This suppresses false positives identified on spring security.
@@ -561,4 +576,36 @@
<gav regex="true">^org\.springframework\.boot:spring-boot-starter-data-jpa:.*$</gav>
<cve>CVE-2016-6652</cve>
</suppress>
<suppress base="true">
<notes><![CDATA[
False positive per issue #699
]]></notes>
<gav regex="true">^com\.splunk:splunk:.*$</gav>
<cpe>cpe:/a:splunk:splunk</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
False positive per issue #713
]]></notes>
<gav regex="true">^org\.openid4java:openid4java:.*$</gav>
<cpe>cpe:/a:openid:openid</cpe>
<cpe>cpe:/a:openid:openid4java</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
False positive per issue #700
]]></notes>
<gav regex="true">^org\.springframework\.cloud:spring-cloud-netflix-core:.*$</gav>
<cpe>cpe:/a:pivotal:spring_framework</cpe>
<cpe>cpe:/a:pivotal_software:spring_framework</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
False positive per issue #700
]]></notes>
<gav regex="true">^org\.springframework\.cloud:spring-cloud-.*$</gav>
<cpe>cpe:/a:pivotal:spring_framework</cpe>
<cpe>cpe:/a:pivotal_software:spring_framework</cpe>
<cpe>cpe:/a:context_project:context</cpe>
</suppress>
</suppressions>

View File

@@ -41,6 +41,8 @@ data.password=DC-Pass1337!
data.driver_name=org.h2.Driver
data.driver_path=
proxy.disableSchemas=true
# the number of days that the modified nvd cve data holds data for. We don't need
# to update the other files if we are within this timespan. Per NIST this file
# holds 8 days of updates, we are using 7 just to be safe.

View File

@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="analysis"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="https://jeremylong.github.io/DependencyCheck/dependency-check.1.5.xsd"
xmlns:dc="https://jeremylong.github.io/DependencyCheck/dependency-check.1.5.xsd">
<xs:complexType name="scanInfo">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="engineVersion" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="dataSource">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="timestamp" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:sequence>
</xs:complexType>
<xs:complexType name="projectInfo">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="groupID" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="artifactID" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="version" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="reportDate" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="credits" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="identifier">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required" />
<xs:attribute name="confidence" type="xs:string" use="optional" />
</xs:complexType>
<xs:complexType name="relatedDependency">
<xs:sequence>
<xs:element name="filePath" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="sha1" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="md5" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="identifier" type="dc:identifier" />
</xs:sequence>
</xs:sequence>
</xs:complexType>
<xs:complexType name="exception">
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="stackTrace" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="trace" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="innerException" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="message" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="stackTrace" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="trace" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="evidence">
<xs:sequence>
<xs:element name="source" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required" />
<xs:attribute name="confidence" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="reference">
<xs:sequence>
<xs:element name="source" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="url" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="software">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="allPreviousVersion" type="xs:boolean" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="vulnerability">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssScore" type="xs:decimal" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssAccessVector" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssAccessComplexity" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssAuthenticationr" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssConfidentialImpact" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssIntegrityImpact" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cvssAvailabilityImpact" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="severity" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="cwe" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="notes" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="references" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="reference" type="dc:reference" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerableSoftware" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="software" type="dc:software" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="dependency">
<xs:sequence>
<xs:element name="fileName" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="filePath" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="md5" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="sha1" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="license" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="relatedDependencies" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="relatedDependency" type="dc:relatedDependency" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="analysisExceptions" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="exception" type="dc:exception"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="evidenceCollected" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="evidence" type="dc:evidence"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="identifiers" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="identifier" type="dc:identifier" />
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="suppressedIdentifier" type="dc:identifier"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="vulnerabilities" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="vulnerability" type="dc:vulnerability"/>
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="suppressedVulnerability" type="dc:vulnerability"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="analysis">
<xs:complexType>
<xs:sequence>
<xs:element name="scanInfo" type="dc:scanInfo"/>
<xs:element name="projectInfo" type="dc:projectInfo"/>
<xs:element name="dependencies">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="dependency" type="dc:dependency"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -0,0 +1,27 @@
#**
This file is part of Dependency-Check.
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.
@author Jeremy Long <jeremy.long@owasp.org>
@version 1 *###
"Project","ScanDate","DependencyName","DependencyPath","Description","License","Md5","Sha1","Identifiers","CPE","CVE","CWE","Vulnerability","Severity","CVSSv2"
#macro(writeSev $score)#if($score<4.0)"Low"#elseif($score>=7.0)"High"#else"Medium"#end#end
#foreach($dependency in $dependencies)#if($dependency.getVulnerabilities().size()>0)
#foreach($vuln in $dependency.getVulnerabilities())
$enc.csv($applicationName),$enc.csv($scanDate),$enc.csv($dependency.DisplayFileName),#if($dependency.FilePath)$enc.csv($dependency.FilePath)#end,#if($dependency.description)$enc.csv($dependency.description)#end,#if($dependency.license)$enc.csv($dependency.license)#end,#if($dependency.Md5sum)$enc.csv($dependency.Md5sum)#end,#if($dependency.Sha1sum)$enc.csv($dependency.Sha1sum)#end,#if($dependency.identifiers)$enc.csvIdentifiers($dependency.identifiers)#end,#if($dependency.identifiers)$enc.csvCpe($dependency.identifiers)#end,#if($vuln.name)$enc.csv($vuln.name)#end,#if($dependency.cwe)$enc.csv($vuln.cwe)#end,#if($vuln.description)$enc.csv($vuln.description)#end,#writeSev($vuln.cvssScore),$vuln.cvssScore
#end
#end
#end

View File

@@ -632,7 +632,7 @@ Getting Help: <a href="https://groups.google.com/forum/#!forum/dependency-check"
#foreach($dependency in $dependencies)
#set($lnkcnt=$lnkcnt+1)
<tr class="#if($dependency.getVulnerabilities().size()==0)notvulnerable#else vulnerable#end">
<td data-sort-value="$enc.html($dependency.DisplayFileName)"><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
<td data-sort-value="$enc.html($dependency.DisplayFileName.toUpperCase())"><a href="#l${lnkcnt}_$enc.html($enc.url($dependency.Sha1sum))">$enc.html($dependency.DisplayFileName)</a></td>
#set($mavenlink="")
#set($cpeIdCount=0)
#set($cpeIdConf="")
@@ -673,9 +673,9 @@ Getting Help: <a href="https://groups.google.com/forum/#!forum/dependency-check"
#if ($mavenlink=="")
<td data-sort-value="">
#else
<td data-sort-value="$enc.html($mavenlink.value)">#if( $mavenlink.url )
<td data-sort-value="$enc.html($mavenlink.value.toLowerCase())">#if( $mavenlink.url )
##yes, we are HTML Encoding the href. This is okay. We can't URL encode as we have to trust the analyzer here...
<a href="$enc.html($mavenlink.url)" target="_blank">$enc.html($mavenlink.value)</a>
<a href="$enc.html($mavenlink.url)" target="_blank">$enc.html($mavenlink.value)</a>&nbsp;<span title="verified from repo" style="color:green">&#x2713;</span>
#elseif ($mavenlink.value)
$enc.html($mavenlink.value)
#end
@@ -762,10 +762,10 @@ Getting Help: <a href="https://groups.google.com/forum/#!forum/dependency-check"
<li>SHA1:&nbsp;$enc.html($related.Sha1sum)</li>
<li>MD5:&nbsp;$enc.html($related.Md5sum)</li>
#foreach($id in $related.getIdentifiers())
#if ($id.type=="maven")
#if( $id.url )
#if( $id.url )
#if ($id.type=="maven")
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li>$enc.html($id.type):&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
<li>$enc.html($id.type):&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>&nbsp;<span title="verified from repo" style="color:green">&#x2713;</span>
#else
<li>$enc.html($id.type):&nbsp;$enc.html($id.value)
#end
@@ -800,8 +800,12 @@ Getting Help: <a href="https://groups.google.com/forum/#!forum/dependency-check"
#end
#foreach($id in $dependency.getIdentifiers())
#if( $id.url )
#if($id.type=="maven")
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>&nbsp;<span title="verified from repo" style="color:green">&#x2713;</span>
#else
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>
#end
#else
<li><b>$enc.html($id.type):</b>&nbsp;$enc.html($id.value)
#end
@@ -949,8 +953,12 @@ Getting Help: <a href="https://groups.google.com/forum/#!forum/dependency-check"
<ul>
#foreach($id in $dependency.getSuppressedIdentifiers())
#if( $id.url )
#if($id.type=="maven")
##yes, we are HTML Encoding the href. this is okay. We can't URL encode as we have to trust the analyzer here...
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>&nbsp;<span title="verified from repo" style="color:green">&#x2713;</span>&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span>
#else
<li><b>$enc.html($id.type):</b>&nbsp;<a href="$enc.html($id.url)" target="_blank">$enc.html($id.value)</a>&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span>
#end
#else
<li><b>$enc.html($id.type):</b>&nbsp;$enc.html($id.value)&nbsp;&nbsp;<span class="suppressedLabel" >suppressed</span>
#end

View File

@@ -0,0 +1,182 @@
{
"reportSchema": "1.0",
"scanInfo": {
"engineVersion": "$version",
"dataSource": [
#foreach($prop in $properties.getMetaData().entrySet())
#if($foreach.count > 1),#end{
"name": "$enc.json($prop.key)",
"timestamp": "$enc.json($prop.value)"
}
#end
]
},
"projectInfo": {
"name": "$enc.json($applicationName)",
#if($groupID)"groupID":"$enc.json($groupID)",#end
#if($artifactID)"artifactID":"$enc.json($artifactID)",#end
#if($version)"version":"$enc.json($version)",#end
"reportDate": "$scanDateXML",
"credits": "This report contains data retrieved from the National Vulnerability Database: http://nvd.nist.gov"
},
"dependencies": [
#foreach($dependency in $dependencies)#if($foreach.count > 1),#end{
"fileName": "$enc.json($dependency.DisplayFileName)",
"filePath": "$enc.json($dependency.FilePath)",
"md5": "$enc.json($dependency.Md5sum)",
"sha1": "$enc.json($dependency.Sha1sum)"
#if($dependency.description),"description": "$enc.json($dependency.description)"#end
#if($dependency.license),"license": "$enc.json($dependency.license)"#end
#if ($dependency.getRelatedDependencies().size()>0)
,"relatedDependencies": [
#foreach($related in $dependency.getRelatedDependencies()) #if($foreach.count > 1),#end {
"filePath": "$enc.json($related.FilePath)",
"sha1": "$enc.json($related.Sha1sum)",
"md5": "$enc.json($related.Md5sum)"#if($related.getIdentifiers()),#end
"identifiers": [
#foreach($id in $related.getIdentifiers())
#if ($id.type=="maven")
{
"type": "$enc.json($id.type)",
"name": "$id.value"
#if( $id.url ),"url": "$enc.json($id.url)"#end
#if ($id.notes),"notes": "$enc.json($id.notes)"#end
}
#end
#end
]
}
#end
]
#end
,"evidenceCollected": {
"vendorEvidence": [
#foreach($evidence in $dependency.getVendorEvidence())
#if($foreach.count > 1),#end{
"type": "vendor",
"confidence": "$enc.json($evidence.getConfidence().toString())",
"source": "$enc.json($evidence.getSource())",
"name": "$enc.json($evidence.getName())",
"value": "$enc.json($evidence.getValue().trim())"
}
#end
],
"productEvidence": [
#foreach($evidence in $dependency.getProductEvidence())
#if($foreach.count > 1),#end{
"type": "product",
"confidence": "$enc.json($evidence.getConfidence().toString())",
"source": "$enc.json($evidence.getSource())",
"name": "$enc.json($evidence.getName())",
"value": "$enc.json($evidence.getValue().trim())"
}
#end
],
"versionEvidence": [
#foreach($evidence in $dependency.getVersionEvidence())
#if($foreach.count > 1),#end{
"type": "version",
"confidence": "$enc.json($evidence.getConfidence().toString())",
"source": "$enc.json($evidence.getSource())",
"name": "$enc.json($evidence.getName())",
"value": "$enc.json($evidence.getValue().trim())"
}
#end
]
},
"identifiers": [
#foreach($id in $dependency.getIdentifiers())#if($foreach.count > 1),#end{
"name": "$id.value",
"type": "$enc.json($id.type)",
#if($id.confidence)"confidence": "$id.confidence",#end
#if($id.url)"url": "$enc.json($id.url)",#end
#if($id.description )"description": "$enc.json($id.description)",#end
#if ($id.notes)"notes": "$enc.json($id.notes)",#end
"suppressedIdentifiers": [
#foreach($id in $dependency.getSuppressedIdentifiers())
#if($foreach.count > 1),#end{
"type": "$enc.json($id.type)",
#if($id.confidence)"confidence": "$id.confidence",#end
"name": "$id.value",
#if($id.url)"url": "$enc.json($id.url),"#end
#if($id.description)"description": "$enc.json($id.description)",#end
#if ($id.notes)"notes": "$enc.json($id.notes)"#end
}
#end
]
}
#end
]
#if($dependency.getVulnerabilities().size()>0 || $dependency.getSuppressedVulnerabilities().size()>0)
,"vulnerabilities": [
#foreach($vuln in $dependency.getVulnerabilities())#if($foreach.count > 1),#end {
"name": "$enc.json($vuln.name)",
"cvssScore": "$vuln.cvssScore",
"cvssAccessVector": "$enc.json($vuln.cvssAccessVector)",
"cvssAccessComplexity": "$enc.json($vuln.cvssAccessComplexity)",
"cvssAuthenticationr": "$enc.json($vuln.cvssAuthentication)",
"cvssConfidentialImpact": "$enc.json($vuln.cvssConfidentialityImpact)",
"cvssIntegrityImpact": "$enc.json($vuln.cvssIntegrityImpact)",
"cvssAvailabilityImpact": "$enc.json($vuln.cvssAvailabilityImpact)",
#if ($vuln.cvssScore<4.0)"severity": "Low",
#elseif ($vuln.cvssScore>=7.0)"severity": "High",
#else "severity": "Medium",#end
"cwe": "#if ($vuln.cwe)$enc.json($vuln.cwe)#end",
"description": "$enc.json($vuln.description)",
"notes": "#if ($vuln.notes)$enc.json($vuln.notes)#end",
"references": [
#foreach($ref in $vuln.getReferences())
#if($foreach.count > 1),#end {
"source": "$enc.json($ref.source)",
"url": "$enc.json($ref.url)",
"name": "$enc.json($ref.name)"
}#end
],
"vulnerableSoftware": [
#foreach($vs in $vuln.getVulnerableSoftware())
#if($foreach.count > 1),#end {
"software": "$enc.json($vs.name)"
#if($vs.hasPreviousVersion()) ,"allPreviousVersion": "true"#end
}#end
]
}#end
]#end
#if($dependency.getSuppressedVulnerabilities().size()>0 || $dependency.getSuppressedVulnerabilities().size()>0)
,"suppressedVulnerabilities": [
#foreach($vuln in $dependency.getSuppressedVulnerabilities())#if($foreach.count > 1),#end {
"name": "$enc.json($vuln.name)",
"cvssScore": "$vuln.cvssScore",
"cvssAccessVector": "$enc.json($vuln.cvssAccessVector)",
"cvssAccessComplexity": "$enc.json($vuln.cvssAccessComplexity)",
"cvssAuthenticationr": "$enc.json($vuln.cvssAuthentication)",
"cvssConfidentialImpact": "$enc.json($vuln.cvssConfidentialityImpact)",
"cvssIntegrityImpact": "$enc.json($vuln.cvssIntegrityImpact)",
"cvssAvailabilityImpact": "$enc.json($vuln.cvssAvailabilityImpact)",
#if ($vuln.cvssScore<4.0) "severity": "Low",
#elseif ($vuln.cvssScore>=7.0) "severity": "High",
#else "severity": "Medium",
#end
"cwe": "#if ($vuln.cwe)$enc.json($vuln.cwe)#end",
"description": "$enc.json($vuln.description)",
"notes": "#if ($vuln.notes)$enc.json($vuln.notes)#end",
"references": [
#foreach($ref in $vuln.getReferences())
#if($foreach.count > 1),#end {
"source": "$enc.json($ref.source)",
"url": "$enc.json($ref.url)",
"name": "$enc.json($ref.name)"
}#end
],
"vulnerableSoftware": [
#foreach($vs in $vuln.getVulnerableSoftware())
#if($foreach.count > 1),#end {
"name": "$enc.json($vs.name)"
#if($vs.hasPreviousVersion()) ,"allPreviousVersion": "true"#end
}#end
]
}#end
]#end
}#end
]
}

View File

@@ -19,7 +19,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
@version 1.2
*#<?xml version="1.0"?>
<analysis xmlns="https://jeremylong.github.io/DependencyCheck/dependency-check.1.4.xsd">
<analysis xmlns="https://jeremylong.github.io/DependencyCheck/dependency-check.1.5.xsd">
<scanInfo>
<engineVersion>$version</engineVersion>
#foreach($prop in $properties.getMetaData().entrySet())
@@ -31,6 +31,15 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</scanInfo>
<projectInfo>
<name>$enc.xml($applicationName)</name>
#if ($groupID)
<groupID>$enc.xml($groupID)</groupID>
#end
#if ($artifactID)
<artifactID>$enc.xml($artifactID)</artifactID>
#end
#if ($version)
<version>$enc.xml($version)</version>
#end
<reportDate>$scanDateXML</reportDate>
<credits>This report contains data retrieved from the National Vulnerability Database: http://nvd.nist.gov</credits>
</projectInfo>

View File

@@ -17,6 +17,7 @@
*/
package org.owasp.dependencycheck;
import java.io.File;
import java.io.IOException;
import static org.junit.Assert.assertTrue;
@@ -29,12 +30,13 @@ import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long
*/
public class EngineIntegrationTest extends BaseDBTestCase {
public class EngineIT extends BaseDBTestCase {
/**
* Test running the entire engine.
@@ -71,12 +73,7 @@ public class EngineIntegrationTest extends BaseDBTestCase {
throw ex;
}
}
DatabaseProperties prop = null;
try (CveDB cve = CveDB.getInstance()) {
prop = cve.getDatabaseProperties();
}
ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), prop);
rg.generateReports("./target/", "ALL");
instance.writeReports("dependency-check sample", new File("./target/"), "ALL");
instance.cleanup();
}
}

View File

@@ -33,7 +33,7 @@ import org.owasp.dependencycheck.utils.Settings;
*
* @author Jeremy Long
*/
public class ArchiveAnalyzerIntegrationTest extends BaseDBTestCase {
public class ArchiveAnalyzerIT extends BaseDBTestCase {
/**
* Test of getSupportedExtensions method, of class ArchiveAnalyzer.

View File

@@ -34,12 +34,14 @@ import org.owasp.dependencycheck.data.cpe.IndexEntry;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long
*/
public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
public class CPEAnalyzerIT extends BaseDBTestCase {
/**
* Tests of buildSearch of class CPEAnalyzer.

View File

@@ -24,7 +24,7 @@ import org.owasp.dependencycheck.BaseDBTestCase;
*
* @author Jeremy Long
*/
public class DependencyBundlingAnalyzerIntegrationTest extends BaseDBTestCase {
public class DependencyBundlingAnalyzerIT extends BaseDBTestCase {
/**
* Test of analyze method, of class DependencyBundlingAnalyzer.

View File

@@ -26,13 +26,15 @@ import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Testing the vulnerability suppression analyzer.
*
* @author Jeremy Long
*/
public class VulnerabilitySuppressionAnalyzerIntegrationTest extends BaseDBTestCase {
public class VulnerabilitySuppressionAnalyzerIT extends BaseDBTestCase {
/**
* Test of getName method, of class VulnerabilitySuppressionAnalyzer.

View File

@@ -34,12 +34,27 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
*
* @author Jeremy Long
*/
public class CveDBIntegrationTest extends BaseDBTestCase {
public class CveDBIT extends BaseDBTestCase {
/**
* Pretty useless tests of open, commit, and close methods, of class CveDB.
@@ -53,8 +68,10 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
} catch (DatabaseException | SQLException ex) {
fail(ex.getMessage());
} finally {
int start = instance.getUsageCount();
instance.close();
assertFalse(instance.isOpen());
int end = instance.getUsageCount();
assertTrue( end < start);
}
}

View File

@@ -28,12 +28,14 @@ import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
*
* @author Jeremy Long
*/
public class CveDBMySQLTest extends BaseTest {
public class CveDBMySqlIT extends BaseTest {
/**
* Pretty useless tests of open, commit, and close methods, of class CveDB.
@@ -47,8 +49,10 @@ public class CveDBMySQLTest extends BaseTest {
System.out.println("Unable to connect to the My SQL database; verify that the db server is running and that the schema has been generated");
fail(ex.getMessage());
} finally {
int start = instance.getUsageCount();
instance.close();
assertFalse(instance.isOpen());
int end = instance.getUsageCount();
assertTrue( end < start);
}
}

View File

@@ -24,12 +24,15 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.data.update.nvd.NvdCveInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long
*/
public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
public class DatabasePropertiesIT extends BaseDBTestCase {
/**
* Test of isEmpty method, of class DatabaseProperties.

View File

@@ -23,12 +23,14 @@ import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.data.update.nvd.UpdateableNvdCve;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
/**
*
* @author Jeremy Long
*/
public class NvdCveUpdaterIntegrationTest extends BaseDBTestCase {
public class NvdCveUpdaterIT extends BaseDBTestCase {
public NvdCveUpdater getUpdater() {
NvdCveUpdater instance = new NvdCveUpdater();

View File

@@ -0,0 +1,231 @@
/*
* 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.reporting;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.dependency.Identifier;
/**
*
* @author jerem
*/
public class EscapeToolTest {
/**
* Test of url method, of class EscapeTool.
*/
@Test
public void testUrl() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.url(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.url(text);
assertEquals(expResult, result);
text = " ";
expResult = "+";
result = instance.url(text);
assertEquals(expResult, result);
}
/**
* Test of html method, of class EscapeTool.
*/
@Test
public void testHtml() {
EscapeTool instance = new EscapeTool();
String text = null;
String expResult = null;
String result = instance.html(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.html(text);
assertEquals(expResult, result);
text = "<div>";
expResult = "&lt;div&gt;";
result = instance.html(text);
assertEquals(expResult, result);
}
/**
* Test of xml method, of class EscapeTool.
*/
@Test
public void testXml() {
EscapeTool instance = new EscapeTool();
String text = null;
String expResult = null;
String result = instance.xml(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.xml(text);
assertEquals(expResult, result);
text = "<div>";
expResult = "&lt;div&gt;";
result = instance.xml(text);
assertEquals(expResult, result);
}
/**
* Test of json method, of class EscapeTool.
*/
@Test
public void testJson() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.json(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.json(text);
assertEquals(expResult, result);
text = "test \"quote\"\"";
expResult = "test \\\"quote\\\"\\\"";
result = instance.json(text);
assertEquals(expResult, result);
}
/**
* Test of csv method, of class EscapeTool.
*/
@Test
public void testCsv() {
String text = null;
EscapeTool instance = new EscapeTool();
String expResult = null;
String result = instance.csv(text);
assertEquals(expResult, result);
text = "";
expResult = "";
result = instance.csv(text);
assertEquals(expResult, result);
text = "one, two";
expResult = "\"one, two\"";
result = instance.csv(text);
assertEquals(expResult, result);
}
/**
* Test of csvIdentifiers method, of class EscapeTool.
*/
@Test
public void testCsvIdentifiers() {
EscapeTool instance = new EscapeTool();
Set<Identifier> ids = null;
String expResult = "";
String result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
expResult = "";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
expResult = "";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "somegroup:something:1.0";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "somegroup:something:1.0";
result = instance.csvIdentifiers(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup2:something:1.2", ""));
expResult = "\"somegroup:something:1.0, somegroup2:something:1.2\"";
String expResult2 = "\"somegroup2:something:1.2, somegroup:something:1.0\"";
result = instance.csvIdentifiers(ids);
assertTrue(expResult.equals(result) || expResult2.equals(result));
}
/**
* Test of csvCpe method, of class EscapeTool.
*/
@Test
public void testCsvCpe() {
EscapeTool instance = new EscapeTool();
Set<Identifier> ids = null;
String expResult = "";
String result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
expResult = "";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
expResult = "cpe:/a:somegroup:something:1.0";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
expResult = "cpe:/a:somegroup:something:1.0";
result = instance.csvCpe(ids);
assertEquals(expResult, result);
ids = new HashSet<>();
ids.add(new Identifier("cpe", "cpe:/a:somegroup:something:1.0", ""));
ids.add(new Identifier("gav", "somegroup:something:1.0", ""));
ids.add(new Identifier("cpe", "cpe:/a:somegroup2:something:1.2", ""));
expResult = "\"cpe:/a:somegroup:something:1.0, cpe:/a:somegroup2:something:1.2\"";
String expResult2 = "\"cpe:/a:somegroup2:something:1.2, cpe:/a:somegroup:something:1.0\"";
result = instance.csvCpe(ids);
assertTrue(expResult.equals(result) || expResult2.equals(result));
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.reporting;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.xml.sax.SAXException;
import static org.junit.Assert.fail;
/**
*
* @author Jeremy Long
*/
public class ReportGeneratorIT extends BaseDBTestCase {
/**
* Generates an XML report containing known vulnerabilities and realistic
* data and validates the generated XML document against the XSD.
*
* @throws Exception
*/
@Test
public void testGenerateReport() {
try {
String templateName = "XmlReport";
File f = new File("target/test-reports");
if (!f.exists()) {
f.mkdir();
}
File writeTo = new File("target/test-reports/Report.xml");
File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml");
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath());
//File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
File struts = BaseTest.getResourceAsFile(this, "struts2-core-2.1.2.jar");
//File axis = new File(this.getClass().getClassLoader().getResource("axis2-adb-1.4.1.jar").getPath());
File axis = BaseTest.getResourceAsFile(this, "axis2-adb-1.4.1.jar");
//File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar");
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine engine = new Engine();
engine.scan(struts);
engine.scan(axis);
engine.scan(jetty);
engine.analyzeDependencies();
engine.writeReports("Test Report", "org.owasp", "dependency-check-core", "1.4.7", writeTo, "XML");
engine.cleanup();
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.5.xsd");
StreamSource xsdSource = new StreamSource(xsdStream);
StreamSource xmlSource = new StreamSource(writeTo);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
} catch (InvalidSettingException ex) {
fail(ex.getMessage());
} catch (DatabaseException | ExceptionCollection | ReportException | SAXException | IOException ex) {
fail(ex.getMessage());
}
}
}

View File

@@ -1,169 +0,0 @@
/*
* 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) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.reporting;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.xml.sax.SAXException;
/**
*
* @author Jeremy Long
*/
public class ReportGeneratorIntegrationTest extends BaseDBTestCase {
/**
* Test of generateReport method, of class ReportGenerator.
*
* @throws Exception is thrown when an exception occurs.
*/
@Test
public void testGenerateReport() throws Exception {
// String templateName = "HtmlReport";
// File f = new File("target/test-reports");
// if (!f.exists()) {
// f.mkdir();
// }
// String writeTo = "target/test-reports/Report.html";
// Map<String, Object> properties = new HashMap<String, Object>();
// Dependency d = new Dependency();
// d.setFileName("FileName.jar");
// d.setActualFilePath("lib/FileName.jar");
// d.addCPEentry("cpe://a:/some:cpe:1.0");
//
// List<Dependency> dependencies = new ArrayList<Dependency>();
// d.getProductEvidence().addEvidence("jar","filename","<test>test", Confidence.HIGH);
// d.getProductEvidence().addEvidence("manifest","vendor","<test>test", Confidence.HIGH);
//
// for (Evidence e : d.getProductEvidence().iterator(Confidence.HIGH)) {
// String t = e.getValue();
// }
// dependencies.add(d);
//
// Dependency d2 = new Dependency();
// d2.setFileName("Another.jar");
// d2.setActualFilePath("lib/Another.jar");
// d2.addCPEentry("cpe://a:/another:cpe:1.0");
// d2.addCPEentry("cpe://a:/another:cpe:1.1");
// d2.addCPEentry("cpe://a:/another:cpe:1.2");
// d2.getProductEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
// d2.getProductEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
//
// for (Evidence e : d2.getProductEvidence().iterator(Confidence.HIGH)) {
// String t = e.getValue();
// }
//
// dependencies.add(d2);
//
// Dependency d3 = new Dependency();
// d3.setFileName("Third.jar");
// d3.setActualFilePath("lib/Third.jar");
// d3.getProductEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
//
// for (Evidence e : d3.getProductEvidence().iterator(Confidence.HIGH)) {
// String t = e.getValue();
// }
//
// dependencies.add(d3);
//
// properties.put("dependencies",dependencies);
//
// ReportGenerator instance = new ReportGenerator();
// instance.generateReport(templateName, writeTo, properties);
//assertTrue("need to add a real check here", false);
}
/**
* Generates an XML report containing known vulnerabilities and realistic data and validates the generated XML document
* against the XSD.
*
* @throws Exception
*/
@Test
public void testGenerateXMLReport() {
try {
String templateName = "XmlReport";
File f = new File("target/test-reports");
if (!f.exists()) {
f.mkdir();
}
String writeTo = "target/test-reports/Report.xml";
File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml");
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath());
//File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
File struts = BaseTest.getResourceAsFile(this, "struts2-core-2.1.2.jar");
//File axis = new File(this.getClass().getClassLoader().getResource("axis2-adb-1.4.1.jar").getPath());
File axis = BaseTest.getResourceAsFile(this, "axis2-adb-1.4.1.jar");
//File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar");
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Engine engine = new Engine();
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
engine.scan(struts);
engine.scan(axis);
engine.scan(jetty);
engine.analyzeDependencies();
CveDB cveDB = CveDB.getInstance();
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers(), dbProp);
generator.generateReport(templateName, writeTo);
cveDB.close();
engine.cleanup();
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.4.xsd");
StreamSource xsdSource = new StreamSource(xsdStream);
StreamSource xmlSource = new StreamSource(new File(writeTo));
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
} catch (InvalidSettingException ex) {
fail(ex.getMessage());
} catch (DatabaseException | ExceptionCollection | ReportException | SAXException | IOException ex) {
fail(ex.getMessage());
}
}
}

View File

@@ -36,6 +36,7 @@ data.password=DC-Pass1337!
data.driver_name=org.h2.Driver
data.driver_path=
proxy.disableSchemas=true
# the number of days that the modified nvd cve data holds data for. We don't need
# to update the other files if we are within this timespan. Per NIST this file
# holds 8 days of updates, we are using 7 just to be safe.

View File

@@ -85,23 +85,6 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/dependency-check-data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
@@ -244,6 +227,13 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<version>2.0.0</version>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.11</version>
</dependency>
</dependencies>
<configuration>
<!--streamLogs>true</streamLogs-->
<!-- The parallel builds cannot be increased beyond 2 as 690 must run before others (can be run parralel to 618 though) -->

View File

@@ -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

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.owasp.test</groupId>
<artifactId>test-system-scope</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<scope>system</scope>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@@ -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.dependencies instanceof List
assert json.dependencies.size()==1
return true;

View File

@@ -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.
*/

View File

@@ -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) 2014 Jeremy Long. All Rights Reserved.
#
invoker.goals = install ${project.groupId}:${project.artifactId}:${project.version}:check -DskipSystemScope=true -Dformat=JSON

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.owasp.test</groupId>
<artifactId>test-system-scope</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<scope>system</scope>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@@ -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.dependencies instanceof List
assert json.dependencies.size()==0
return true;

View File

@@ -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) 2014 Jeremy Long. All Rights Reserved.
*/

View File

@@ -22,6 +22,19 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
<artifactId>test-dataformat-jackson</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>redhat</id>
<name>redhat</name>
<url>https://maven.repository.redhat.com/ga/</url>
</repository>
<repository>
<id>spring</id>
<name>spring</name>
<url>http://repo.spring.io/plugins-release/</url>
</repository>
</repositories>
<dependencies>
<!-- False Positives from issue #642 -->
<dependency>
@@ -29,6 +42,37 @@ Copyright (c) 2017 Jeremy Long. All Rights Reserved.
<artifactId>spring-boot</artifactId>
<version>1.4.3.RELEASE</version>
</dependency>
<!-- end issue #642 -->
<!-- End Issue #642 -->
<!-- False Positives from issue #699 -->
<dependency>
<groupId>com.splunk</groupId>
<artifactId>splunk</artifactId>
<version>1.6.2.0</version>
</dependency>
<!-- End Issue #699 -->
<!-- False Positives from issue #700 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>1.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>1.1.7.RELEASE</version>
</dependency>
<!-- End Issue #700 -->
<!-- False Positives from issue #713 -->
<dependency>
<groupId>org.openid4java</groupId>
<artifactId>openid4java</artifactId>
<version>0.9.7</version>
</dependency>
<!-- End Issue #713 -->
</dependencies>
</project>

View File

@@ -20,16 +20,6 @@ import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import java.nio.charset.Charset;
// Save NVD-CVE for next IT (if not already done)
File datasDwl = new File("target/local-repo/org/owasp/dependency-check-data/3.0", "dc.h2.db");
File datasSave = new File("target/nvd-cve-backup", "dc.h2.db");
if (datasDwl.exists() && !datasSave.exists()){
System.out.println("Save NVD-CVE into backup");
FileUtils.copyFile(datasDwl, datasSave);
}
// Check to see if jackson-dataformat-xml-2.4.5.jar was identified.
//TODO change this to xpath and check for CVE-2016-3720

View File

@@ -123,7 +123,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
outputDir = new File(this.getProject().getBuild().getDirectory());
}
try {
writeReports(engine, this.getProject(), outputDir);
final MavenProject p = this.getProject();
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat());
} catch (ReportException ex) {
if (exCol == null) {
exCol = new ExceptionCollection("Error writing aggregate report", ex);

View File

@@ -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;
@@ -117,7 +118,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* The Maven Session.
*/
@Parameter(defaultValue = "${session}", readonly = true, required = true)
protected MavenSession session;
private MavenSession session;
/**
* Remote repositories which will be searched for artifacts.
@@ -403,6 +404,13 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
@SuppressWarnings("CanBeFinal")
@Parameter(property = "skipProvidedScope", defaultValue = "false", required = false)
private boolean skipProvidedScope = false;
/**
* Skip Analysis for Provided Scope Dependencies.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "skipSystemScope", defaultValue = "false", required = false)
private boolean skipSystemScope = false;
/**
* The data directory, hold DC SQL DB.
*/
@@ -627,24 +635,54 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* @return a collection of exceptions that may have occurred while resolving
* and scanning the dependencies
*/
private ExceptionCollection collectDependencies(Engine engine, MavenProject project, List<DependencyNode> nodes, ProjectBuildingRequest buildingRequest) {
private ExceptionCollection collectDependencies(Engine engine, MavenProject project,
List<DependencyNode> nodes, ProjectBuildingRequest buildingRequest) {
ExceptionCollection exCol = null;
for (DependencyNode dependencyNode : nodes) {
exCol = collectDependencies(engine, project, dependencyNode.getChildren(), buildingRequest);
if (excludeFromScan(dependencyNode.getArtifact().getScope())) {
continue;
}
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<Dependency> 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<Dependency> 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",
@@ -682,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
@@ -756,6 +821,10 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
return "dependency-check-report.xml#";
} else if ("VULN".equalsIgnoreCase(this.format)) {
return "dependency-check-vulnerability";
} else if ("JSON".equalsIgnoreCase(this.format)) {
return "dependency-check-report.json";
} else if ("CSV".equalsIgnoreCase(this.format)) {
return "dependency-check-report.csv";
} else {
getLog().warn("Unknown report format used during site generation.");
return "dependency-check-report";
@@ -962,6 +1031,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
if (skipProvidedScope && org.apache.maven.artifact.Artifact.SCOPE_PROVIDED.equals(scope)) {
return true;
}
if (skipSystemScope && org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals(scope)) {
return true;
}
return skipRuntimeScope && !org.apache.maven.artifact.Artifact.SCOPE_RUNTIME.equals(scope);
}
@@ -997,34 +1069,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
return format;
}
/**
* Generates the reports for a given dependency-check engine.
*
* @param engine a dependency-check engine
* @param p the Maven project
* @param outputDir the directory path to write the report(s)
* @throws ReportException thrown if there is an error writing the report
*/
protected void writeReports(Engine engine, MavenProject p, File outputDir) throws ReportException {
DatabaseProperties prop = null;
try (CveDB cve = CveDB.getInstance()) {
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
//TODO shouldn't this throw an exception?
if (getLog().isDebugEnabled()) {
getLog().debug("Unable to retrieve DB Properties", ex);
}
}
final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
try {
r.generateReports(outputDir.getAbsolutePath(), format);
} catch (ReportException ex) {
final String msg = String.format("Error generating the report for %s", p.getName());
throw new ReportException(msg, ex);
}
}
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
/**
* Checks to see if a vulnerability has been identified with a CVSS score

View File

@@ -25,6 +25,7 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
@@ -99,33 +100,32 @@ public class CheckMojo extends BaseDependencyCheckMojo {
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
if (engine.getDependencies().isEmpty()) {
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
} else {
try {
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
if (this.isFailOnError() && ex.isFatal()) {
throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
}
exCol = ex;
}
try {
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
if (this.isFailOnError() && ex.isFatal()) {
throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
}
if (exCol == null || !exCol.isFatal()) {
try {
writeReports(engine, getProject(), getCorrectOutputDirectory());
} catch (ReportException ex) {
if (this.isFailOnError()) {
if (exCol != null) {
exCol.addException(ex);
} else {
exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
}
exCol = ex;
}
if (exCol == null || !exCol.isFatal()) {
try {
final MavenProject p = this.getProject();
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), getCorrectOutputDirectory(), getFormat());
} catch (ReportException ex) {
if (this.isFailOnError()) {
if (exCol != null) {
exCol.addException(ex);
} else {
exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
}
}
//writeDataFile(getProject(), null, engine.getDependencies());
showSummary(getProject(), engine.getDependencies());
checkForFailure(engine.getDependencies());
if (exCol != null && this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
}
}
showSummary(getProject(), engine.getDependencies());
checkForFailure(engine.getDependencies());
if (exCol != null && this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
}
}
engine.cleanup();

View File

@@ -19,13 +19,14 @@ cveValidForHours | Sets the number of hours to wait before checking f
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
failBuildOnAnyVulnerability | Specific that if any vulnerability is identified, the build will fail. | false
failOnError | Whether the build should fail if there is an error executing the dependency-check analysis. | true
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
format | The report format to be generated (HTML, XML, CSV, JSON, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
name | The name of the report in the site. | dependency-check or dependency-check:aggregate
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build. | 'target'
skip | Skips the dependency-check analysis. | false
skipTestScope | Skip analysis for artifacts with Test Scope. | true
skipProvidedScope | Skip analysis for artifacts with Provided Scope. | false
skipRuntimeScope | Skip analysis for artifacts with Runtime Scope. | false
skipSystemScope | Skip analysis for artifacts with System Scope. | false
skipTestScope | Skip analysis for artifacts with Test Scope. | true
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html). | &nbsp;
hintsFile | The file path to the XML hints file \- used to resolve [false negatives](../general/hints.html). | &nbsp;
enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false

View File

@@ -41,62 +41,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<configuration>
<!--instrumentation>
<ignoreTrivial>true</ignoreTrivial>
</instrumentation-->
<check>
<branchRate>85</branchRate>
<lineRate>85</lineRate>
<haltOnFailure>false</haltOnFailure>
<totalBranchRate>85</totalBranchRate>
<totalLineRate>85</totalLineRate>
<packageLineRate>85</packageLineRate>
<packageBranchRate>85</packageBranchRate>
<regexes>
<regex>
<pattern>.*\$.*</pattern>
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
</regexes>
</check>
</configuration>
<executions>
<execution>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
</plugins>
</build>
<reporting>

View File

@@ -185,6 +185,12 @@ public final class Settings {
* The properties key for the URL to retrieve the CPE.
*/
public static final String CPE_URL = "cpe.url";
/**
* Whether or not if using basic auth with a proxy the system setting
* 'jdk.http.auth.tunneling.disabledSchemes' should be set to an empty
* string.
*/
public static final String PROXY_DISABLE_SCHEMAS = "proxy.disableSchemas";
/**
* The properties key for the proxy server.
*

View File

@@ -67,12 +67,12 @@ public final class URLConnectionFactory {
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE", justification = "Just being extra safe")
public static HttpURLConnection createHttpURLConnection(URL url) throws URLConnectionFailureException {
HttpURLConnection conn = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_SERVER);
final String proxyHost = Settings.getString(Settings.KEYS.PROXY_SERVER);
try {
if (proxyUrl != null && !matchNonProxy(url)) {
if (proxyHost != null && !matchNonProxy(url)) {
final int proxyPort = Settings.getInt(Settings.KEYS.PROXY_PORT);
final SocketAddress address = new InetSocketAddress(proxyUrl, proxyPort);
final SocketAddress address = new InetSocketAddress(proxyHost, proxyPort);
final String username = Settings.getString(Settings.KEYS.PROXY_USERNAME);
final String password = Settings.getString(Settings.KEYS.PROXY_PASSWORD);
@@ -81,7 +81,15 @@ public final class URLConnectionFactory {
final Authenticator auth = new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
if (proxyHost.equals(getRequestingHost()) || getRequestorType().equals(Authenticator.RequestorType.PROXY)) {
LOGGER.debug("Using the configured proxy username and password");
try {
if (Settings.getBoolean(Settings.KEYS.PROXY_DISABLE_SCHEMAS, true)) {
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
}
} catch (InvalidSettingException ex) {
LOGGER.trace("This exception can be ignored", ex);
}
return new PasswordAuthentication(username, password.toCharArray());
}
return super.getPasswordAuthentication();

View File

@@ -21,12 +21,13 @@ import java.io.File;
import java.net.URL;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long
*/
public class DownloaderIntegrationTest extends BaseTest {
public class DownloaderIT extends BaseTest {
/**
* Test of fetchFile method, of class Downloader.

View File

@@ -36,6 +36,7 @@ data.password=DC-Pass1337!
data.driver_name=org.h2.Driver
data.driver_path=
proxy.disableSchemas=true
# the path to the cpe xml file
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz
# the path to the cpe meta data file.

97
pom.xml
View File

@@ -30,6 +30,7 @@ Copyright (c) 2012 - Jeremy Long
<module>dependency-check-maven</module>
<module>dependency-check-utils</module>
<module>dependency-check-plugin</module>
<module>build-reporting</module>
</modules>
<name>Dependency-Check</name>
<url>https://github.com/jeremylong/DependencyCheck.git</url>
@@ -132,7 +133,6 @@ Copyright (c) 2012 - Jeremy Long
<!-- Note that Maven will use classes from the distro, ignoring declared dependencies for Maven core... -->
<maven.api.version>3.0</maven.api.version>
<reporting.checkstyle-plugin.version>2.17</reporting.checkstyle-plugin.version>
<reporting.cobertura-plugin.version>2.7</reporting.cobertura-plugin.version>
<reporting.pmd-plugin.version>3.6</reporting.pmd-plugin.version>
</properties>
<distributionManagement>
@@ -162,9 +162,9 @@ Copyright (c) 2012 - Jeremy Long
<version>1.10</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -278,19 +278,83 @@ Copyright (c) 2012 - Jeremy Long
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>add-dynamic-properties</id>
<phase>pre-integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.properties['invoker.mavenOpts']=project.properties.failsafeArgLine
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefireArgLine} -Dfile.encoding=UTF-8</argLine>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/data</value>
</property>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<argLine>${failsafeArgLine}</argLine>
<systemProperties>
<property>
<name>temp.directory</name>
<value>${project.build.directory}/temp</value>
</property>
</systemProperties>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
<excludes>
<exclude>**/*MySqlIT.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
@@ -529,13 +593,19 @@ Copyright (c) 2012 - Jeremy Long
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${reporting.cobertura-plugin.version}</version>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<configuration>
<dataFileIncludes>
<dataFileInclude>target/coverage-reports/jacoco-ut.exec</dataFileInclude>
<dataFileInclude>target/coverage-reports/jacoco-it.exec</dataFileInclude>
</dataFileIncludes>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>cobertura</report>
<report>report-aggregate</report>
</reports>
</reportSet>
</reportSets>
@@ -597,6 +667,11 @@ Copyright (c) 2012 - Jeremy Long
<artifactId>annotations</artifactId>
<version>3.0.1u2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>

View File

@@ -20,8 +20,8 @@ To setup a centralized database the following generalized steps can be used:
<ol><li>Create the database and tables using either <a href="https://github.com/jeremylong/DependencyCheck/blob/master/dependency-check-core/src/main/resources/data/initialize.sql">initialize.sql</a>
or one of the other initialization scripts <a href="https://github.com/jeremylong/DependencyCheck/tree/master/dependency-check-core/src/main/resources/data">found here</a>.</li>
<li>The account that the clients will connect using must have select granted on the tables.
<ul><li>Note, if the clients performing the scans should run with the noupdate setting. A single
instance of the dependency-check client should be setup with update enabled and the account
<ul><li>Note, the clients performing the scans should run with the noupdate setting. A single
instance of the dependency-check client should be setup with updates enabled and the account
used during the update process will need to be granted update rights on the tables.
</li></ul>
</li><li>Dependency-check clients running scans will need to be configured to use the central database:

View File

@@ -17,7 +17,7 @@ autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is ena
cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD. | 4
failOnError | Fails the build if an error occurs during the dependency-check analysis. | true
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11; since the CVSS scores are 0-10, by default the build will never fail. | 11
format | The report format to be generated (HTML, XML, VULN, ALL). | HTML
format | The report format to be generated (HTML, XML, CSV, JSON, VULN, ALL). | HTML
outputDirectory | The location to write the report(s). This directory will be located in the build directory. | build/reports
skipTestGroups | When set to true (the default) all dependency groups that being with 'test' will be skipped. | true
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) | &nbsp;

View File

@@ -0,0 +1,2 @@
# Jacoco Aggregate Report
The test coverage reports can be found [here](../build-reporting/jacoco-aggregate/index.html).