Compare commits

...

1269 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
d2a8645dd4 expanded test cases to include additional dependencies 2017-04-29 09:39:30 -04:00
Jeremy Long
4543835a0d reset threadcount to zero as the plugin is not yet threadsafe 2017-04-29 09:33:52 -04:00
Jeremy Long
c0f41c461b reverted the threadsafe flag as the plugin is not threadsafe 2017-04-29 09:32:58 -04:00
Jeremy Long
116ef264e1 updated failing test case to expect the correct exception 2017-04-26 08:59:53 -04:00
Jeremy Long
1371dacdaa expanded test case to identify/fix threading issue 2017-04-26 08:50:39 -04:00
Jeremy Long
d252d0f29f fixed threading issue 2017-04-26 08:50:06 -04:00
Jeremy Long
3786f6ebc7 removed un-needed code from invoker build scripts 2017-04-26 07:30:33 -04:00
Jeremy Long
6813427867 updated invoker plugin to use 2 threads 2017-04-26 07:30:01 -04:00
Jeremy Long
f94cf106a6 re-route invoker logs so the results can be viewed in travis 2017-04-25 08:01:09 -04:00
Jeremy Long
a67e421a5d nop 2017-04-23 08:44:24 -04:00
Jeremy Long
865db1b6c3 nop 2017-04-23 08:04:54 -04:00
Jeremy Long
31d7379a39 minor updates and added documentation 2017-04-23 07:22:53 -04:00
Jeremy Long
f473e63a61 added test case and added locking mechanism so only one update can run at any given time 2017-04-23 07:05:31 -04:00
Jeremy Long
c9ee55863f fixed merge 2017-04-12 10:42:02 -04:00
Jeremy Long
238a96184a Merge branch 'master' into issue690_threadsafe 2017-04-12 10:28:16 -04:00
Jeremy Long
44ddad8101 updated for maven thread safety 2017-04-12 10:24:51 -04:00
Jeremy Long
afa47f7dfc Merge pull request #695 from jeremylong/fix_coverity_finding
Fix coverity findings
2017-04-12 10:24:24 -04:00
Jeremy Long
f289bcd285 fixed false positive per issue #691 2017-04-04 10:03:19 -04:00
Jeremy Long
c7adb1bb65 fix for issue #684 2017-04-04 09:58:19 -04:00
Jeremy Long
4bbc5e27b5 updated 2017-04-02 13:24:07 -04:00
Jeremy Long
c877ade004 updated 2017-04-02 13:22:35 -04:00
Jeremy Long
ebd8996ad5 fixed typo 2017-04-02 13:12:45 -04:00
Jeremy Long
f31313d021 added PR template 2017-04-02 13:08:58 -04:00
Jeremy Long
6936dac9b4 updated template 2017-04-02 13:08:42 -04:00
Jeremy Long
4b2f6832fe added contributing guidelines 2017-04-02 12:58:17 -04:00
Jeremy Long
c622ff2b19 converted to using jacoco for code coverage 2017-04-02 08:16:21 -04:00
Jeremy Long
35d0f21c47 fix codacy issues 2017-04-01 10:02:24 -04:00
Jeremy Long
3066d286c5 added logo no text 2017-04-01 09:58:32 -04:00
Jeremy Long
18564e8e86 fixed merge issue 2017-04-01 08:33:13 -04:00
Jeremy Long
832cbabc7d added bh arsenal badges 2017-03-31 17:28:20 -04:00
Jeremy Long
8b764d5e17 added bh arsenal badges 2017-03-31 17:24:48 -04:00
Jeremy Long
e2a1a59543 fixed issues related to making the cveDb a singleton 2017-03-31 06:58:37 -04:00
Jeremy Long
cedb8d3db1 Merge pull request #689 from jwilk/mailto
Fix mailto URIs
2017-03-25 09:13:11 -04:00
Jeremy Long
539bd754df fixed merge 2017-03-25 09:10:41 -04:00
Jeremy Long
109f5c22e9 initial fix for CveDB singleton 2017-03-25 09:06:34 -04:00
Jeremy Long
a23d127c62 initial fix for CveDB singleton 2017-03-25 09:05:51 -04:00
Jakub Wilk
6825304100 fix mailto URIs
As per RFC 6068, there should be no slashes after "mailto:".
2017-03-24 16:09:23 +01:00
Jeremy Long
947499726a initial attempt 2017-03-15 07:36:28 -04:00
Jeremy Long
97b2e1a4da added documentation per issue https://github.com/jeremylong/dependency-check-gradle/issues/38 2017-03-14 09:06:17 -04:00
Prakhash
2b04c6a7dd changed the coordinates according to the pom file details 2017-03-13 15:52:50 +05:30
Jeremy Long
3bb6553111 Merge pull request #681 from jeremylong/java7_updates_and_cleanup
Java7 updates and cleanup
2017-03-12 19:35:12 -04:00
Jeremy Long
371dba948d checkstyle corrections 2017-03-12 18:03:27 -04:00
Jeremy Long
675349c06f fixed broken test case 2017-03-12 15:59:23 -04:00
Jeremy Long
7a88981aa4 updated to use try with resouces 2017-03-12 13:22:27 -04:00
Jeremy Long
626f6c3de2 updated to use IOUtils to copy between streams 2017-03-12 13:21:59 -04:00
Jeremy Long
5540397456 Merge pull request #680 from jeremylong/cvedb
Cvedb
2017-03-11 14:45:49 -05:00
Jeremy Long
69c6dd40a1 fixed synchronization on local variable 2017-03-11 14:24:46 -05:00
Jeremy Long
5ed6e838fc spelling corrections 2017-03-11 14:15:24 -05:00
Jeremy Long
1d32a6012a fixed possible NPE 2017-03-11 13:28:21 -05:00
Jeremy Long
b157049a7e use try with resources 2017-03-11 13:27:40 -05:00
Jeremy Long
8ea6b08a0a use try with resources 2017-03-11 13:26:56 -05:00
Jeremy Long
8856ff04ec code cleanup and java 7 exception handling improvements 2017-03-11 12:46:58 -05:00
Jeremy Long
8bfbd11a51 added test cases 2017-03-11 12:46:06 -05:00
Jeremy Long
abd843d281 simplified conditional 2017-03-11 11:11:31 -05:00
Jeremy Long
c54f9b1144 fixed throws in finally and converted to try with resources 2017-03-11 11:11:02 -05:00
Jeremy Long
318f3e14dd removed unused code for batching 2017-03-11 11:10:21 -05:00
Jeremy Long
46f227e92e updated and added test cases 2017-03-11 11:09:31 -05:00
Jeremy Long
a7b6f37503 suppressed another false positive 2017-03-10 16:52:32 -05:00
Jeremy Long
a61bba2f72 code cleanup 2017-03-10 16:40:22 -05:00
Jeremy Long
dfc6d952bd codacy cleanup 2017-03-10 15:38:00 -05:00
Jeremy Long
046f4605f9 java7 updates and cleanup 2017-03-10 15:30:48 -05:00
Jeremy Long
32590ab7ff Merge branch 'master' of github.com:jeremylong/DependencyCheck into cvedb 2017-03-10 14:00:53 -05:00
Jeremy Long
efeb084e57 added suppression rule for jcore per issue #679 2017-03-10 06:51:53 -05:00
Jeremy Long
03ec3142c3 updated threadpool size 2017-03-07 06:37:21 -05:00
Jeremy Long
679df936e7 changed CveDB to a singeton 2017-03-07 05:49:12 -05:00
Jeremy Long
5ed5764ab5 Merge branch 'stefanneuhaus-misc_performance_tweaking_and_cleanup' 2017-03-04 14:29:47 -05:00
Jeremy Long
d588092727 Merge branch 'misc_performance_tweaking_and_cleanup' of https://github.com/stefanneuhaus/DependencyCheck into stefanneuhaus-misc_performance_tweaking_and_cleanup 2017-03-04 14:20:01 -05:00
Jeremy Long
295ba0679d Merge branch 'aikebah-master' 2017-03-04 14:02:40 -05:00
Jeremy Long
bcdf26c88d Merge branch 'master' of https://github.com/aikebah/DependencyCheck into aikebah-master 2017-03-04 13:51:28 -05:00
Jeremy Long
d6e092bfa2 Merge pull request #676 from jwilk/spelling
Fix typos
2017-03-04 13:50:09 -05:00
Jeremy Long
388c1b5af1 java 7 updates 2017-03-04 13:47:53 -05:00
Jakub Wilk
717aea9a03 fix typos 2017-03-02 23:07:35 +01:00
Stefan Neuhaus
4951ee5a62 Cleanup: Codacy conformance 2017-02-28 08:23:57 +01:00
Jeremy Long
666150cf7f updated per issue #672 2017-02-27 08:35:07 -05:00
Jeremy Long
d8290c0c45 Merge pull request #674 from jeremylong/Prakhash-reportmodifier1
Prakhash reportmodifier1
2017-02-26 10:02:01 -05:00
Jeremy Long
e363e8109b added suppression notes 2017-02-26 09:16:53 -05:00
Jeremy Long
b228d08843 removed typo 2017-02-26 09:16:16 -05:00
Jeremy Long
3e08437808 updated to work with new schema 2017-02-26 07:52:02 -05:00
Jeremy Long
e0d5651b75 updated to add notes 2017-02-26 07:50:35 -05:00
Jeremy Long
59e29b7afe Merge branch 'notes' into Prakhash-reportmodifier1 2017-02-25 16:09:21 -05:00
Jeremy Long
d180208e34 interim 2017-02-25 16:08:44 -05:00
Jeremy Long
0ce1ef596c Merge branch 'reportmodifier1' of https://github.com/Prakhash/DependencyCheck into Prakhash-reportmodifier1 2017-02-25 15:55:12 -05:00
Jeremy Long
5f7486f851 updates to 673 2017-02-25 15:53:12 -05:00
Jeremy Long
03559fd106 added more suppression rules for false positives 2017-02-25 06:31:34 -05:00
Jeremy Long
d08357a1c2 fixed typo 2017-02-24 07:10:27 -05:00
Jeremy Long
c1cb87ebde Merge branch 'master' of github.com:jeremylong/DependencyCheck 2017-02-24 06:30:11 -05:00
Jeremy Long
82fd1cf4d7 additional fp added 2017-02-24 06:30:02 -05:00
Prakhash
a87391e609 formatting issues reported by the codacy is fixed 2017-02-24 14:54:45 +05:30
Prakhash
3071cfd7be formatting issues reported by the codacy is done 2017-02-24 14:43:46 +05:30
Prakhash
583c2d34d3 schema changes are added with global schema 2017-02-24 14:23:56 +05:30
Prakhash
c9640fbf04 schema file is modified with notes attribute' 2017-02-24 12:15:21 +05:30
Prakhash
192d1de944 name space changes are reverted to the original 2017-02-24 12:06:51 +05:30
Prakhash
aa0314c840 report is modified with the notes element 2017-02-24 11:03:10 +05:30
Hans Aikema
0171b859c6 Merge branch 'master' of https://github.com/jeremylong/DependencyCheck 2017-02-23 11:22:25 +01:00
Jeremy Long
d267e14b73 Merge pull request #666 from colezlaw/grokassembly
Updated GrokAssembly and added config
2017-02-22 06:32:45 -05:00
Hans Aikema
79e63f4067 Merge remote-tracking branch 'upstream/master' 2017-02-21 17:35:30 +01:00
Hans Aikema
72d7af5291 Enable running DependencyCheck on Maven 3.0 2017-02-21 17:31:46 +01:00
Stefan Neuhaus
0e313d1910 Fix issue 2017-02-21 17:06:02 +01:00
Stefan Neuhaus
6841f9a009 Fix typo in directory name 2017-02-21 16:17:36 +01:00
Stefan Neuhaus
caeec68999 Refactor CveDB
- make class thread-safe and declare so (also DatabaseProperties)
- prepared statements represented by enum: performance gain, eases experiments when tuning for performance
- minor changes/cleanup/code style
2017-02-21 14:32:24 +01:00
Stefan Neuhaus
541915a5a7 Minor improvements in NvdCve20Handler
- use addAll() instead of iterating and adding single instances for VulnerableSoftware
- define String constants for certain XML attributes: code style, could facilitate JVM optimizations
2017-02-21 14:30:22 +01:00
Stefan Neuhaus
cb75ab8cca Use Apache StringUtils.split(String, char) instead of String.split(String)
String.split() uses a regex pattern for splitting. As we simply need to split on a single fixed char using the Apache StringUtils is preferable.
2017-02-21 14:23:13 +01:00
Stefan Neuhaus
0f3845b16d cleanup: remove unused return value 2017-02-21 14:12:12 +01:00
Stefan Neuhaus
dd7128095e add license information to dbStatements_oracle.properties 2017-02-21 14:02:34 +01:00
Jeremy Long
1367be510c correct fix for issue #660; correctly handle organization from the pom 2017-02-21 07:02:05 -05:00
Jeremy Long
2ea0eb3c64 correct fix for issue #660; correctly handle organization from the pom 2017-02-21 06:40:02 -05:00
Jeremy Long
a5990ea6f3 update to #657 to allow sorted vulnerable software in repots; also, sorting an array list is faster then building a treeset 2017-02-21 06:38:31 -05:00
colezlaw
67921f5f3d Updated GrokAssembly and added config 2017-02-20 15:35:52 -05:00
Jeremy Long
d31e0453bd fix for #660 2017-02-20 07:01:05 -05:00
stevespringett
ae21424a30 Closes #664 2017-02-18 21:23:19 -06:00
Jeremy Long
3577949425 codacy recommended updates 2017-02-17 19:03:53 -05:00
Jeremy Long
0d72471502 fixed synchronization per coverity 2017-02-17 18:00:40 -05:00
Jeremy Long
17590a6d38 re-ordered badges 2017-02-17 17:58:36 -05:00
Jeremy Long
d9dcc8cc2d fixed UTF-8 BOM bug 2017-02-17 17:18:10 -05:00
Jeremy Long
df1ee5e8c6 reverted dependency-tree to resolve bug 2017-02-17 17:17:54 -05:00
Jeremy Long
3c68ebece7 plugin/dependency upgrades 2017-02-17 14:35:51 -05:00
Jeremy Long
c9e8e6cf0e codacy recommended updates 2017-02-17 14:20:43 -05:00
Jeremy Long
36945fb84d added codacy badge 2017-02-17 13:05:12 -05:00
Jeremy Long
960a2e27ab formating and codacy recommended updates 2017-02-17 12:59:17 -05:00
Jeremy Long
71724461a9 Merge branch 'stefanneuhaus-accelerate-db-update_parallelize-fetching-lastmodification-timestamps' 2017-02-17 12:14:02 -05:00
Jeremy Long
ae5a95bfb3 merge #662 2017-02-17 12:13:45 -05:00
Jeremy Long
d6c9fea354 formating and codacy recommended updates 2017-02-17 12:03:11 -05:00
Jeremy Long
d6f1351f6b Merge pull request #657 from stefanneuhaus/accelerate-db-update_get-rid-of-treeset
Accelerate CVE DB update: replace TreeSets in Vulnerability by HashSets
2017-02-17 10:48:46 -05:00
Jeremy Long
373488adb4 codacy recommended updates 2017-02-17 10:31:25 -05:00
Stefan Neuhaus
59401cc9f8 cleanup/code style 2017-02-16 20:55:26 +01:00
Stefan Neuhaus
eca0e7a852 Fix integration test 2017-02-16 20:53:48 +01:00
Stefan Neuhaus
563dc24854 Parallelize retrieval of last modification timestamps 2017-02-16 08:59:09 +01:00
Stefan Neuhaus
3a70e25983 Refactoring: Move retrieval of last modified timestamps from UpdateableNvdCve to NvdCveUpdater
- UpdateableNvdCve is from its nature more like a simple value object
- Facilitates performance optimization for retrieval of last modification timestamps
2017-02-16 08:58:50 +01:00
Stefan Neuhaus
a9fc6bf02c cleanup: remove unused stuff 2017-02-16 08:58:36 +01:00
Stefan Neuhaus
cd4f09dc86 NvdCveUpdater: Refactor thread pool concept
- Make thread pools members of the class to facilitate reuse
- Increase default max download thread pool size from 3 to 50 (should be fine for mostly blocking tasks like downloading)
2017-02-16 08:58:14 +01:00
Jeremy Long
4193718571 upgrade to Java 7 2017-02-12 17:42:19 -05:00
Stefan Neuhaus
0464626e2b Accelerate CVE DB update
Vulnerability: switch vulnerableSoftware and references from expensive TreeSet to HashSet
2017-02-11 20:46:28 +01:00
Jeremy Long
a0198e34e7 snapshot version 2017-02-09 06:04:02 -05:00
Jeremy Long
0b329bd40e added test case 2017-02-07 19:41:06 -05:00
Jeremy Long
3d33f24f09 Merge pull request #655 from suhand/master
Minor spelling fixes
2017-02-07 19:40:39 -05:00
Jeremy Long
886c02fad2 add configuration to remove FP based on parent-group/artifact from spring-boot 2017-02-07 06:24:34 -05:00
Jeremy Long
3a11504153 updated to prevent bundling of dependencies within WAR files 2017-02-07 06:22:55 -05:00
Jeremy Long
3a082ae00a minor update to #617 2017-02-07 06:06:53 -05:00
Suhan Dharmasuriya
780201845b Minor spelling fixes 2017-02-07 12:00:17 +05:30
Jeremy Long
0e0a4bb0b4 expanded hint rules so that they can remove evidence 2017-02-04 09:20:47 -05:00
Jeremy Long
5333083a78 fixed bug that caused ODC to fail if an invalid assembly was scanned 2017-01-28 08:13:27 -05:00
Jeremy Long
b8c6c86330 snapshot version 2017-01-28 08:12:51 -05:00
Jeremy Long
e246757f47 version 1.4.5 2017-01-22 17:10:42 -05:00
Jeremy Long
4172300799 added license 2017-01-22 16:11:50 -05:00
Jeremy Long
f39f754b7b reapplied fix for issue #601 2017-01-22 08:10:14 -05:00
Jeremy Long
c59615f452 patch for issue #510 and #512 2017-01-22 08:01:40 -05:00
Jeremy Long
847bed2fa0 added manifest implementation-version 2017-01-22 07:42:11 -05:00
Jeremy Long
a9af15f6f8 checkstyle/pmd suggested corrections 2017-01-21 08:47:52 -05:00
Jeremy Long
92519ae955 updated notes 2017-01-21 08:09:48 -05:00
Jeremy Long
2d90aca1f2 minor code cleanup 2017-01-21 08:05:54 -05:00
Jeremy Long
f29ed38c34 Merge pull request #644 from oosterholt/master
Add troubling JAR file name to the exception when JAR reading errors occur
2017-01-21 06:21:18 -05:00
Rick Oosterholt
df8d4fd77c Minor change: When JAR reading errors occur, at least add the file name
to the exception. Without it, finding the troubling JAR is hard.
2017-01-18 13:52:17 +01:00
Jeremy Long
baa2e2c6ff updated archetype for new analyzers to be more complete 2017-01-15 12:18:01 -05:00
Jeremy Long
9d5769bb69 Merge branch 'issue575' 2017-01-15 11:19:37 -05:00
Jeremy Long
4cdfa804ee fixed accidental commit 2017-01-14 09:43:34 -05:00
Jeremy Long
523cd23b6b filter version numbers for issue #575 2017-01-14 09:41:34 -05:00
Jeremy Long
61866e9e76 updated source version 2017-01-14 08:55:20 -05:00
Jeremy Long
ff7fbdc98d updated year to speed test case 2017-01-14 07:34:35 -05:00
Jeremy Long
b625d642ea updated documentation for #635 2017-01-14 07:31:31 -05:00
Jeremy Long
8733a85ebb patch per issue#642 2017-01-13 06:53:26 -05:00
Jeremy Long
5ab5a7b72b tuned linguist language stats 2017-01-09 20:05:37 -05:00
Jeremy Long
3cb8b9fa9e Merge branch 'hgschmie-additional_analyzers' 2017-01-08 11:52:09 -05:00
Jeremy Long
429039bf1c documentation for issue #635 2017-01-08 11:37:50 -05:00
Jeremy Long
29d28c3408 fixed PR #635 to cover other interfaces 2017-01-08 11:23:52 -05:00
Jeremy Long
372d484440 Merge branch 'additional_analyzers' of https://github.com/hgschmie/DependencyCheck into hgschmie-additional_analyzers 2017-01-08 10:33:57 -05:00
Jeremy Long
eac47800a3 added documentation for PR #636 2017-01-08 08:55:29 -05:00
Jeremy Long
86a85db12b removed for now 2017-01-08 08:54:47 -05:00
Jeremy Long
4ab6cd278c updated documentation for PR #636 2017-01-08 08:51:56 -05:00
Jeremy Long
233a068c8b Merge pull request #636 from hgschmie/fail_on_any_vuln
adds a new flag 'failBuildOnAnyVulnerability'
2017-01-08 08:19:24 -05:00
Jeremy Long
d9f0ffa742 Merge pull request #634 from hgschmie/enable_disable
rework the enabled / disabled logic
2017-01-08 08:18:12 -05:00
Jeremy Long
8d63ee19ed fix for Jenkins integration, updates to commit f47c6b0 2017-01-08 07:55:35 -05:00
Jeremy Long
1fb74e1a27 Merge pull request #639 from dejan2609/java-6-compatibility
check code against Java 1.6 API signatures
2017-01-07 06:40:47 -05:00
dejan2609
c94ab6108c check code against Java 1.6 API signatures 2017-01-04 16:42:07 +01:00
Jeremy Long
bf285e19ab added site for archetype 2017-01-02 21:59:09 -05:00
Jeremy Long
b1ceca73e4 added plugin archetype to site 2017-01-02 21:48:04 -05:00
Jeremy Long
f3aca63b61 version upgrades and added enforcer for java version 2017-01-02 21:47:27 -05:00
Jeremy Long
fca107d287 added site distribution 2017-01-02 21:46:15 -05:00
Jeremy Long
64b6964fff checkstyle corrections 2017-01-02 21:45:49 -05:00
Jeremy Long
6af0842838 added logging 2017-01-02 21:45:21 -05:00
Jeremy Long
4c49adf1ba reduced code duplication 2017-01-02 21:44:59 -05:00
Jeremy Long
5f4e4fab56 reduced code duplication 2017-01-02 21:43:51 -05:00
Jeremy Long
146d7e3fbf reduced code duplciation 2017-01-02 21:42:20 -05:00
Jeremy Long
4d22800747 fixed type 2017-01-02 21:40:57 -05:00
Jeremy Long
541a7f8180 removed unused code 2017-01-02 21:40:04 -05:00
Jeremy Long
f205cf79c9 Merge branch 'plugins' 2016-12-30 17:02:32 -05:00
Jeremy Long
d8bb6488b7 added archetype per #612 2016-12-30 17:01:09 -05:00
Jeremy Long
4324563c0a updated plugins path for #612 2016-12-30 16:42:37 -05:00
Jeremy Long
bad03660b1 added plugins directory per #612 2016-12-29 07:38:11 -05:00
Henning Schmiedehausen
20b1ff38f9 adds a new flag 'failBuildOnAnyVulnerability'
In our build system, we enable checkers based on boolean
values. Currently, the only way to enable failing the build on
vulnerabilities is by providing a numeric value (0-10) for another
property. This change adds a boolean switch that will fail the build
if any vulnerability is present (we have a strict "no vulnerabilities
in our builds" policy).
2016-12-28 17:24:26 -08:00
Henning Schmiedehausen
def78a3cfd rework the enabled / disabled logic
If an analyzer is disabled from the configuration, it should not be
initialized (because some of the may actually fail during that process
nor should the engine log in any way that those exist.

With these changes, it is possible for me to turn off unwanted
analyzers (e.g. Ruby analyzers for a java project) from the maven
plugin and not confuse my users with spurious misleading messages.
2016-12-28 16:39:25 -08:00
Henning Schmiedehausen
a41158a716 adds maven configuration switches for more analyzers 2016-12-28 16:38:28 -08:00
Jeremy Long
63ad13ff7a added enabled properties per issue #612 2016-12-27 08:46:04 -05:00
Jeremy Long
dd92ec675f fixed error in tests 2016-12-27 08:45:42 -05:00
Jeremy Long
6e1512f7d9 added enabled setting (#612) and added additional checks to see if the update should occur (#631) 2016-12-27 08:45:01 -05:00
Jeremy Long
287b1df3fd added enabled settings for all analyzers per #612 2016-12-26 09:11:26 -05:00
Jeremy Long
38bf9b4ddb checkstyle recommendations 2016-12-22 07:32:04 -05:00
Jeremy Long
f9d3a9d8d8 Merge pull request #614 from stefanneuhaus/issue-613-fix-version-comparison
Fix handling of numerical versions
2016-12-22 06:58:26 -05:00
Jeremy Long
309a5d9bcb Merge branch 'issue630' 2016-12-22 06:57:04 -05:00
Jeremy Long
60e661d3a4 updated per issue #630 2016-12-22 06:55:26 -05:00
Jeremy Long
c33257d266 addded synchronization - as this analyzer should only run synchronized 2016-12-22 06:53:35 -05:00
Jeremy Long
1dbc183567 added check for failure 2016-12-22 06:52:47 -05:00
Jeremy Long
bf258146da added test case for issue #629 and #517 2016-12-18 12:14:35 -05:00
Jeremy Long
bb927b447e updated so that the old suppression files could be processed 2016-12-18 12:12:57 -05:00
Jeremy Long
d91b4c3151 updated test case for performance of build 2016-12-18 12:12:10 -05:00
Jeremy Long
91dbb39f18 updated test for #630 2016-12-18 11:59:59 -05:00
Jeremy Long
35ae8fd660 updated test for #630 2016-12-18 11:59:30 -05:00
Jeremy Long
d854917090 changes for issue #630 2016-12-18 11:58:58 -05:00
Jeremy Long
32ebf6c8ed added phase to accomodate the fix for issue #630 2016-12-18 11:58:20 -05:00
Jeremy Long
edd4191d47 fix for #517 2016-12-16 06:29:42 -05:00
Jeremy Long
0cce49506a added validation 2016-12-10 19:58:05 -05:00
Jeremy Long
1c053469e9 fixed date format for test case 2016-12-10 19:50:09 -05:00
Jeremy Long
610e97ef7f jacks suggested change 2016-12-10 16:55:58 -05:00
Jeremy Long
5a678d2ccb removed test code 2016-12-10 16:55:38 -05:00
Jeremy Long
8db61a4d1e coverity suggested change 2016-12-10 16:42:32 -05:00
Jeremy Long
f47c6b07f4 jacks recommended change for thread safety 2016-12-05 22:41:15 -05:00
Jeremy Long
bd3af45db9 fixed code duplication 2016-12-04 16:18:01 -05:00
Jeremy Long
a271d422f6 moved similiar code to a utility function to remove code duplication 2016-12-04 11:28:53 -05:00
Jeremy Long
4dd6dedaa4 hardening the XML parser per jacks.codiscope.com 2016-12-03 17:44:49 -05:00
Jeremy Long
10ee569096 fix proposed by Jacks - synchronizing SimpleDateFormat 2016-12-03 17:43:24 -05:00
Jeremy Long
1474855305 fix proposed by Jacks - synchronizing SimpleDateFormat 2016-12-03 17:41:32 -05:00
Jeremy Long
0202bc11d4 null checking proposed by coverity 2016-12-03 17:39:57 -05:00
Stefan Neuhaus
e7072ea04c Count "0" as a positive integer 2016-12-03 22:50:20 +01:00
Jeremy Long
8f2c755f21 checkstyle correction 2016-12-03 16:23:53 -05:00
Jeremy Long
e513a79bd2 fixed issue #272 2016-12-03 15:07:33 -05:00
Jeremy Long
dd17f7393f snapshot version 2016-12-03 14:28:36 -05:00
Jeremy Long
32f38bf892 updated travis build script 2016-12-03 14:01:32 -05:00
Jeremy Long
d5c3eeaf28 Merge branch 'removeMavenEngine' 2016-12-03 13:48:03 -05:00
Jeremy Long
bfa67fcba7 fix #617 2016-12-03 13:46:25 -05:00
Jeremy Long
37a556dcc0 add integration test 2016-12-03 07:06:01 -05:00
Jeremy Long
fe61f298f0 Merge branch 'axel3rd-MavenMojosPurgeAndUpdateOnlyAggregator' 2016-12-03 06:56:01 -05:00
Jeremy Long
9786c9bf82 minor changes - planning on moving additional testing profile to an invoker test in the maven module per issue #618 2016-12-03 06:55:24 -05:00
Jeremy Long
668161081a moved the invoker plugin to a profile so that it does not execute on every build 2016-12-03 06:54:03 -05:00
Jeremy Long
4978f9dcba Merge branch 'MavenMojosPurgeAndUpdateOnlyAggregator' of https://github.com/axel3rd/DependencyCheck into axel3rd-MavenMojosPurgeAndUpdateOnlyAggregator 2016-11-22 19:57:27 -05:00
Jeremy Long
a6ca2e3895 Merge pull request #625 from axel3rd/MinorFixAndUTsWindowsSpaceDirectory
UTs on Windows when project path contains space & some exception review
2016-11-22 19:51:54 -05:00
Alix Lourme
6ecf55be91 UTs on Windows when project path contains space & some exception review 2016-11-22 23:33:40 +01:00
Jeremy Long
13bd63dac8 re-loading of properties/settings resolved by sharing the settings object amongst tasks 2016-11-22 16:40:57 -05:00
Jeremy Long
db5ff1bfca java mail - disputed CVE is considered a false positive 2016-11-22 16:38:45 -05:00
Jeremy Long
42f2385bb2 updated documentation for PR #619 2016-11-22 06:51:21 -05:00
Jeremy Long
e9556bbbf0 added analyzer initialization so that temp files get put in the correct location 2016-11-22 06:40:33 -05:00
Jeremy Long
316b936326 ensured resources are closed 2016-11-22 06:39:50 -05:00
Jeremy Long
6838b9b950 fixed logic for single pom entry in a jar 2016-11-22 06:21:30 -05:00
Jeremy Long
cdfe5d0c9a Merge pull request #619 from willowtreeapps/feature/fail-on-cvss
Adds a failOnCVSS command line option
2016-11-22 05:50:45 -05:00
Jeremy Long
1610f14c47 general code cleanup/fixes 2016-11-22 05:46:35 -05:00
Jeremy Long
85ab894b94 fixed the possible creation of two indexes 2016-11-20 06:49:28 -05:00
Alix Lourme
ddbca24f33 Maven mojos 'purge' & 'update-only' aggregator #618 2016-11-19 00:32:10 +01:00
Charlie Fairchild
6b9acac8c4 Minor Styling 2016-11-17 15:37:21 -05:00
Charlie Fairchild
2333bee5fd Adds a command line option for the CLI tool to pick what CVSS error to fail on 2016-11-16 11:25:21 -05:00
Jeremy Long
2ad08d2367 minor code cleanup 2016-11-13 16:33:39 -05:00
Stefan Neuhaus
1337686013 Fix handling of numerical versions 2016-11-13 19:37:29 +01:00
Jeremy Long
41041bfd18 updated documentation per issue #607 2016-11-12 11:21:40 -05:00
Jeremy Long
e693e53630 updated error message per issue #607 2016-11-12 11:19:48 -05:00
Jeremy Long
b99e13a337 added documentation to address issue #609 2016-11-12 11:03:25 -05:00
Jeremy Long
3bbc485968 fix index out of range exception per issue #611 2016-11-11 10:58:14 -05:00
Jeremy Long
e0b549e427 v1.4.4 2016-11-05 09:34:53 -04:00
Jeremy Long
75207169e3 resolved fp per #604 2016-11-05 06:29:43 -04:00
Jeremy Long
e07f568237 resolved false positive per #608 2016-11-05 06:23:06 -04:00
Jeremy Long
e2cd99d40d modified code for #606 2016-11-03 06:41:37 -04:00
Jeremy Long
27f2682a98 checkstyle corrections 2016-10-31 06:44:51 -04:00
Jeremy Long
34a2110e9a minor perforance improvement 2016-10-31 06:29:32 -04:00
Jeremy Long
96ba51db4f updated so that all scanned dependencies are correctly kept in the dependency list 2016-10-31 06:29:08 -04:00
Jeremy Long
9c6053a60a fixed logging bug 2016-10-28 19:18:20 -04:00
Jeremy Long
358367ef9e updated documentation to resolve issues #523 and #561 2016-10-28 18:58:27 -04:00
Jeremy Long
a12bc44ecd moved hard-coded configuration to properties file and added some additional debugging 2016-10-28 08:44:43 -04:00
Jeremy Long
773ac019f8 coverity recommended changes 2016-10-23 07:20:24 -04:00
Jeremy Long
e751b7b814 checkstyle correction 2016-10-23 07:02:36 -04:00
Jeremy Long
824aa23b9b updated documentation to reflect that the gradle plugin automatically registers itself when the Java plugin is used 2016-10-23 06:18:50 -04:00
Jeremy Long
b7b97960a6 improvements to the vulnerability report per issue #599 2016-10-22 07:11:36 -04:00
Jeremy Long
40f0e907e1 typo fix per #603 2016-10-22 06:02:59 -04:00
Jeremy Long
5ff0dc885d Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-10-21 07:06:55 -04:00
Jeremy Long
e70a0ee238 corrected how project references are propogated when the same dependency is analyzed more then once 2016-10-21 07:06:47 -04:00
Jeremy Long
9338697079 fixed dctemp path from being the primary dependency 2016-10-21 07:05:21 -04:00
Jeremy Long
4018a4e1de Merge pull request #602 from spyhunter99/feature/601
#601 make the dependency vulnerability count easier to pull out of th…
2016-10-21 05:39:44 -04:00
Alex
e8788dd2a4 #601 make the dependency vulnerability count easier to pull out of the html 2016-10-18 20:08:43 -04:00
Jeremy Long
e70c2f2b05 fixed issue #570 - each instance of dependency-check will have its own temporary folder 2016-10-16 07:40:18 -04:00
Jeremy Long
5ed0583039 added new temp directory creation function 2016-10-16 07:36:38 -04:00
Jeremy Long
f76d7295f9 fixed generics warning 2016-10-16 07:33:09 -04:00
Jeremy Long
6e280c4958 suppressed warnings 2016-10-16 07:32:48 -04:00
Jeremy Long
48b4ef1944 updated duration reporting to be the same format 2016-10-16 07:32:05 -04:00
Jeremy Long
9150df964f fixed error handling 2016-10-16 07:31:17 -04:00
Jeremy Long
b2237394e1 updated duration reporting to be the same format 2016-10-16 07:30:01 -04:00
Jeremy Long
b3a0f7ad26 fixed generic warnings 2016-10-16 07:28:50 -04:00
Jeremy Long
782ba42abc fixed warning regarding no uid 2016-10-16 07:28:09 -04:00
Jeremy Long
74b93ce602 fixing PR #598 2016-10-14 13:47:39 -04:00
Jeremy Long
e907c40f17 Merge pull request #595 from bloihl/master
syncing documentation hints terminology for all sub-projects
2016-10-09 16:14:23 -04:00
bloihl
13a9dedb1e Merge remote-tracking branch 'upstream/master' 2016-10-09 12:54:12 -07:00
bloihl
b37698f245 syncing references to false negatives in documentation 2016-10-09 12:52:44 -07:00
Jeremy Long
d30d000346 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-10-09 15:39:09 -04:00
Jeremy Long
446239a5bd clearly document Maven 3.1 or higher is required 2016-10-09 15:39:02 -04:00
Jeremy Long
ac25aa795b Merge pull request #588 from wurstbrot/master
Add Dockerfile for dependency check
2016-10-09 15:06:44 -04:00
Jeremy Long
f117a9ded0 Merge pull request #594 from stefanneuhaus/parallelize-analyzers-aftermath
Parallelize analyzers aftermath
2016-10-09 15:01:16 -04:00
Stefan Neuhaus
947d38ccd2 Merge remote-tracking branch 'upstream/master' into parallelize-analyzers-aftermath
# Conflicts:
#	dependency-check-core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java
#	dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java
2016-10-09 17:13:39 +02:00
Jeremy Long
23f7996db8 checkstyle corrections 2016-10-09 11:00:28 -04:00
Stefan Neuhaus
9fdff51f26 Merge remote-tracking branch 'upstream/master' into parallelize-analyzers-aftermath 2016-10-09 16:08:46 +02:00
Stefan Neuhaus
9b43bf004a Cleanup
- shutdown() ExecutorService after task execution
- javadoc
- improve unit test coverage
2016-10-09 16:03:36 +02:00
Jeremy Long
5d73faa1f0 updated sample report with the latest version 2016-10-09 08:11:53 -04:00
Jeremy Long
9e70279b31 updated presentation 2016-10-09 08:03:03 -04:00
Jeremy Long
9e671d1065 updated documentation per #556 2016-10-09 08:00:02 -04:00
Jeremy Long
7e2c4af0b3 Merge branch 'bloihl-master' 2016-10-09 07:13:47 -04:00
Jeremy Long
11f9092a65 fixed description 2016-10-09 07:13:35 -04:00
Jeremy Long
6017e5c217 Merge branch 'master' of https://github.com/bloihl/DependencyCheck into bloihl-master 2016-10-09 06:56:17 -04:00
Jeremy Long
b2149ff4b9 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-10-09 06:50:50 -04:00
Jeremy Long
1a5177c576 Merge branch 'stefanneuhaus-parallelize-analyzers' 2016-10-09 06:50:09 -04:00
Jeremy Long
7020c9931a Merge branch 'parallelize-analyzers' of https://github.com/stefanneuhaus/DependencyCheck into stefanneuhaus-parallelize-analyzers 2016-10-09 06:33:10 -04:00
Jeremy Long
9bc43e2e8e Merge pull request #590 from stefanneuhaus/cleanup
Cleanup
2016-10-08 22:07:49 -04:00
Jeremy Long
26a4e7451e Merge pull request #589 from pierre-ernst/master
Hardening
2016-10-08 22:04:07 -04:00
Stefan Neuhaus
3470d33bdc Fix build 2016-10-09 02:59:32 +02:00
Stefan Neuhaus
51c96894b4 Support parallelism for analyzers of the same type 2016-10-09 00:45:10 +02:00
Jeremy Long
7fc2be6a0a corrected checksum calculation so that files can be deleted shortly after the calculation is completed. 2016-10-08 18:05:55 -04:00
Jeremy Long
110c97bc15 ensuring no input stream is left open 2016-10-08 18:02:53 -04:00
Jeremy Long
8d51d8fa1f improved error reporting 2016-10-08 18:00:47 -04:00
Jeremy Long
4b02a567e0 improved error reporting 2016-10-08 18:00:18 -04:00
Stefan Neuhaus
5a939ec108 Provide proper error message in case the (default) property file is not available. Ran into this issue in combination with the Gradle daemon. 2016-10-08 20:00:43 +02:00
Stefan Neuhaus
d9c4480627 Fix typos 2016-10-08 19:40:04 +02:00
Jeremy Long
9388340e23 updated to resolve reported false negative: https://groups.google.com/forum/#!topic/dependency-check/LjnemiZKeZQ 2016-10-08 06:19:46 -04:00
pernst
2285d2ef4b first commit 2016-10-06 16:40:39 -04:00
Timo Pagel
f84aea0040 MOD: Use https over http and fetch current release 2016-10-06 19:38:22 +02:00
bloihl
452969cc92 Merge remote-tracking branch 'upstream/master' 2016-10-04 09:45:01 -07:00
Jeremy Long
128a600f18 fixed issue with cpeSort being null on first row if no CPE is present 2016-10-04 06:45:17 -04:00
Jeremy Long
7dd9a52e78 corrected false positive per issue #582 2016-10-04 06:20:34 -04:00
Jeremy Long
ff341b7228 corrected false positive per issue #582 2016-10-04 06:19:41 -04:00
bloihl
92a8b4ca85 Merge remote-tracking branch 'upstream/master' 2016-10-03 11:12:01 -07:00
bloihl
384199b28d fixed typo in exception and added documentation for hints schema 2016-10-03 09:52:58 -07:00
Jeremy Long
44edcabe15 fixed duplicate analysis identified in https://github.com/jeremylong/dependency-check-gradle/issues/19 2016-10-01 06:55:37 -04:00
Timo Pagel
1a5e9884fc Add usage for docker to the Readme 2016-09-23 12:26:17 +02:00
Timo Pagel
cda81315d2 Add Dockerfile with own user 2016-09-23 12:25:58 +02:00
Jeremy Long
d7100e54d1 made exitValue check more robust to cover possible future negative exit values 2016-09-21 14:21:50 -04:00
Jeremy Long
989caead9c Merge pull request #568 from xthk/bundler-return-code
fixed check for bundle-audit's return code
2016-09-21 14:07:09 -04:00
Jeremy Long
a9d3b627f1 Merge pull request #564 from awhitford/Upg20160918
Upgrades
2016-09-21 14:06:25 -04:00
Jeremy Long
99a1606df1 stopped writting the serialized dc data 2016-09-21 14:05:19 -04:00
Jeremy Long
6326513c63 improved suppression capability within the report 2016-09-21 14:04:21 -04:00
bloihl
f6cfae595a add false negatives General menu 2016-09-20 21:34:34 -07:00
bloihl
0794efcf41 add general hints document explaining false negatives 2016-09-20 21:01:27 -07:00
bloihl
b9ea82f2c1 adding hints documentation for user management of false negatives 2016-09-20 15:42:49 -07:00
bloihl
8b705b3370 update maven docs with hintsFile option 2016-09-20 15:41:26 -07:00
bloihl
c684607a4d updte gradle docs with hintsFile option 2016-09-20 15:41:02 -07:00
bloihl
b00833c2de update ant docs with hintsFile option 2016-09-20 15:40:37 -07:00
bloihl
0ca6bc6ab6 exposing hints to maven through configuration using hintsFile 2016-09-20 12:42:35 -07:00
bloihl
60faddff9b exposing hints file through ant configuration as setHintsFile 2016-09-20 12:40:07 -07:00
bloihl
b35da8ad4b exposing the hints file to the CLI with new option "--hints" 2016-09-20 12:37:58 -07:00
Tilmann Haak
79887c148a fixed check for bundle-audit's return code 2016-09-20 13:43:28 +02:00
Bob Loihl
1ae3457ee6 Merge remote-tracking branch 'upstream/master'
Syncing with master project
2016-09-19 11:36:47 -07:00
Anthony Whitford
d2154c9d29 maven-plugin-annotations 3.5 released. 2016-09-18 23:00:50 -07:00
Anthony Whitford
40ede24a99 Upgraded plugins and dependencies. 2016-09-18 22:30:12 -07:00
Jeremy Long
5960ba919d removed slf4j binding as maven 3.1 no longer requires it, see issue #552 2016-09-16 12:32:24 -04:00
Jeremy Long
f6aaaa8815 updated pre-req per issue #560 2016-09-16 10:25:40 -04:00
Jeremy Long
6f1b20c936 updated report to be able to suppress by GAV and added help text 2016-09-16 10:14:48 -04:00
Jeremy Long
7734a50427 resolve issue #554 2016-09-10 07:20:49 -04:00
Jeremy Long
aef118d375 test and fix for version number matching per issue #558 2016-09-09 06:36:56 -04:00
bloihl
22cae71999 Merge pull request #1 from jeremylong/master
updating fork to latest
2016-09-07 13:49:31 -07:00
Jeremy Long
29d127303c snapshot version 2016-09-06 20:34:22 -04:00
Jeremy Long
5574f1c24f version 1.4.3 2016-09-06 07:04:34 -04:00
Jeremy Long
9457744571 using more robust check for windows os 2016-09-06 06:42:12 -04:00
Jeremy Long
19243c479c disabling batch support for mysql to fix issue #503 - more testing needs to be done 2016-09-06 06:36:08 -04:00
Jeremy Long
e868ce8328 cleaned up file deletion code slightly 2016-09-06 06:23:55 -04:00
Jeremy Long
ffa846c05a updated compareTo so that null values are handled properly 2016-09-06 05:48:12 -04:00
Jeremy Long
dde1791476 minor rewording of a log statement 2016-09-06 05:47:44 -04:00
Jeremy Long
45438a7f06 removed temporary test code 2016-09-05 06:46:06 -04:00
Jeremy Long
c980e77ea3 added assume to skip errors when mono is not installed 2016-09-04 20:50:14 -04:00
Jeremy Long
176d3ddefa temporary fix for issue #534 2016-09-04 19:09:08 -04:00
Jeremy Long
98d783d448 added todo for NPE reasons 2016-09-04 18:51:07 -04:00
Jeremy Long
bcd6634d8a fixed NPE issues 2016-09-04 18:41:58 -04:00
Jeremy Long
0b260cef2a removed duplicated test 2016-09-04 08:00:43 -04:00
Jeremy Long
6a68abbd67 fixed unit test on non-windows 2016-09-01 06:12:35 -04:00
Jeremy Long
9fcf23c802 coverity, checkstyle, pmd, and findbugs suggested corrections 2016-09-01 05:46:09 -04:00
Jeremy Long
5c2c08e051 suppressed false positive, see issue #540 2016-08-30 06:12:17 -04:00
Jeremy Long
1f254997e1 patch to resolve issue #547 2016-08-28 07:46:42 -04:00
Jeremy Long
4f95af0864 removed config 2016-08-27 13:52:05 -04:00
Jeremy Long
6ff39be9d2 initial config 2016-08-27 13:41:29 -04:00
Jeremy Long
6cf5a47971 re-added the check for https that was accidentally removed 2016-08-27 11:43:33 -04:00
Jeremy Long
56da53c700 update for issue #523 - removed specific algorithm list to support differences in JDKs (ibm); just setting the protocol resolves the issue 2016-08-27 07:26:59 -04:00
Jeremy Long
7091e10795 added coverity badge 2016-08-23 21:19:01 -04:00
Jeremy Long
34765c5741 coverity suggested corrections - removed dead local store 2016-08-23 19:24:25 -04:00
Jeremy Long
36c139872a coverity suggested corrections 2016-08-23 19:20:54 -04:00
Jeremy Long
1e77cec677 improved error reporting for issue #547 2016-08-23 19:12:04 -04:00
Jeremy Long
e95e3fb2d0 coverity suggested corrections 2016-08-21 18:40:28 -04:00
Jeremy Long
39c2234e38 coverity suggested corrections 2016-08-21 16:51:09 -04:00
Jeremy Long
f4fff5d9cb checkstyle and formating updates 2016-08-21 15:59:47 -04:00
Jeremy Long
659785f972 checkstyle correction 2016-08-21 15:28:55 -04:00
Jeremy Long
85c04f6e3e checkstyle correction 2016-08-21 15:28:49 -04:00
Jeremy Long
bef117cbe8 coverity correction 2016-08-21 15:28:10 -04:00
Jeremy Long
46dd7cf86e checkstyle correction 2016-08-21 15:27:34 -04:00
Jeremy Long
9ed5a97267 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-08-21 14:41:08 -04:00
Jeremy Long
cc2da70db2 updated ignore list 2016-08-21 14:41:01 -04:00
Jeremy Long
cedd93e774 coverity suggested corrections 2016-08-21 14:40:07 -04:00
Jeremy Long
632e1692eb Merge pull request #541 from biancajiang/swift_support
cocoapods and swift package manager support
2016-08-21 08:03:52 -04:00
Jeremy Long
4861592d2a assume no NPE due to issue with mock and some versions of the JDK 2016-08-21 07:25:37 -04:00
Jeremy Long
22e6d4edf3 updated jdk used by travis 2016-08-21 07:24:54 -04:00
Jeremy Long
e9bd7ff72f Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-08-21 07:11:56 -04:00
Jeremy Long
e7228fb489 updated jdk used by travis 2016-08-21 07:11:17 -04:00
Jeremy Long
96c03a68f2 Merge pull request #545 from colezlaw/grokassemblyfix
Updated GrokAssembly to deal with non-UTF-8 chars in types
2016-08-20 12:24:21 -04:00
Jeremy Long
4f6f248421 reworked aggregation mojo to resolve issues #325, #386, and #531 2016-08-20 12:15:49 -04:00
Will Stranathan
a8f14c86fd Updated GrokAssembly to deal with non-UTF-8 chars in types 2016-08-20 09:34:15 -04:00
Jeremy Long
36de3d1e25 removed unnecassary stacktrace from logs per issue #544 2016-08-18 09:59:21 -04:00
Jeremy Long
48bc4570e1 Merge pull request #542 from bodewig/document_skip_and_scanConfigurations
document skipConfigurations and scanConfigurations for gradle plugin
2016-08-14 06:48:19 -04:00
Stefan Bodewig
94b272dbae document skipConfigurations and scanConfigurations
closes jeremylong/dependency-check-gradle/#12
2016-08-14 11:10:38 +02:00
bjiang
c093edf459 update copyright and javadoc 2016-08-12 17:12:12 -04:00
bjiang
0164feffcc Merge branch 'master' into swift_support 2016-08-12 16:35:12 -04:00
bjiang
8cd377b99f use value of specification-version as version from Manifest 2016-08-12 13:32:25 -04:00
bjiang
74282c8ac5 filter out version from jar filename for name 2016-08-12 13:15:29 -04:00
Jeremy Long
d2158e5e44 fixed typo 2016-08-11 21:12:47 -04:00
Jeremy Long
9ea16ad1d1 skipped patch for Java 1.6 & 1.7 if the JRE is at least 1.8 - see issue #523 2016-08-11 20:59:26 -04:00
Jeremy Long
45941adb71 fixed type per issue #533 2016-08-11 20:55:36 -04:00
Jeremy Long
c4d662fd2b patch for issue #536 2016-08-11 20:49:27 -04:00
Jeremy Long
d9ce3cda66 snapshot version 2016-08-11 20:09:34 -04:00
Jeremy Long
6bd7d6b078 version 1.4.2 2016-07-31 08:01:47 -04:00
Jeremy Long
84c6dd5dfa resolved gradle issue 14 - https://github.com/jeremylong/dependency-check-gradle/issues/14 2016-07-31 07:34:09 -04:00
Jeremy Long
71e7412f15 corrected example 2016-07-31 07:32:30 -04:00
Jeremy Long
d22c920b35 version 1.4.1 2016-07-30 06:52:48 -04:00
Jeremy Long
f7a0982ca0 checkstyle corrections 2016-07-29 06:12:40 -04:00
Jeremy Long
bed04150e1 reverted H2 upgrade due to issues with Jenkins and Java 6 compatability 2016-07-27 06:23:56 -04:00
Jeremy Long
ba15de2218 improved error handling 2016-07-27 06:04:56 -04:00
Jeremy Long
e9ec89dc9c improved error handling 2016-07-27 06:04:08 -04:00
Jeremy Long
d09f75658c minor formating correction 2016-07-24 08:47:27 -04:00
Jeremy Long
62f92db181 added issue template 2016-07-24 08:44:09 -04:00
Jeremy Long
27a98f4244 checckstyle corrections 2016-07-24 08:12:57 -04:00
Jeremy Long
f0a3482eda findbugs correction 2016-07-24 08:07:39 -04:00
Jeremy Long
5f76843c4a findbugs correction 2016-07-24 08:06:54 -04:00
Jeremy Long
c6ea92cff9 added links to the SBT plugin 2016-07-24 07:33:28 -04:00
Jeremy Long
c253308284 checkstyle corrections 2016-07-23 07:45:48 -04:00
Jeremy Long
9ae9c111e3 checkstyle corrections 2016-07-23 07:13:09 -04:00
Jeremy Long
4894372eee minor code quality issues corrected 2016-07-23 06:50:11 -04:00
Jeremy Long
7cf040653f upgraded h2 db version 2016-07-22 06:29:01 -04:00
Jeremy Long
034bd4dba0 testing fix to resolve connection issues with NVD 2016-07-19 07:04:24 -04:00
Jeremy Long
af12a2161c testing fix to resolve connection issues with NVD 2016-07-19 06:54:25 -04:00
Jeremy Long
57fcf6fde3 testing connection errors 2016-07-17 08:18:47 -04:00
Jeremy Long
c5757dc5f4 updates to resolve issue #215 2016-07-17 07:19:56 -04:00
Jeremy Long
6d5d5ceb7b Updated exception handling so that issue #215 can be resolved 2016-07-14 06:31:54 -04:00
bjiang
2fa8507d69 merge owasp 1.4.1 2016-07-12 16:22:05 -04:00
Jeremy Long
f23003ead3 fields can be final 2016-07-10 07:13:08 -04:00
Jeremy Long
c996f6b436 improved exception handling as part of resolution for #215 2016-07-10 07:12:43 -04:00
Jeremy Long
d2ee66a1c4 there was no need to extend IOException 2016-07-10 07:11:03 -04:00
Jeremy Long
26b0dd5ef5 updated javadoc 2016-07-10 06:56:26 -04:00
Jeremy Long
ad4149a259 updated documentation for PR #528 2016-07-10 06:27:40 -04:00
Jeremy Long
9611c3b478 Merge pull request #528 from felfert/master
Thanks for the PR!
2016-07-10 06:13:09 -04:00
Jeremy Long
cead88d221 reworked initialization exceptions as part of planned resolution for issue #215 2016-07-09 07:39:00 -04:00
Jeremy Long
c1e1a6bb4f cleaned up imports 2016-07-09 07:35:36 -04:00
Fritz Elfert
6212a5f740 Compatibility fixes for MariaDB JDBC driver 2016-07-08 22:27:10 +02:00
Jeremy Long
b3d9ea3c47 minor code reorg 2016-07-07 06:18:54 -04:00
Jeremy Long
cd51989354 Merge pull request #526 from nicolastrres/master
Updating gradle dependencyCheck documentation
2016-07-07 06:05:12 -04:00
nicolastrres
b705ae5f0c Updating gradle dependencyCheck documentation 2016-07-06 14:57:24 -03:00
Jeremy Long
13b53537fa incorrectly set quick query value during recheck - see issue #523 2016-07-06 06:48:10 -04:00
Jeremy Long
7d05aa6073 added logging for issue #523 2016-07-06 06:44:43 -04:00
Jeremy Long
85de173086 fixed StackOverflowError from issue #523 2016-07-06 06:32:57 -04:00
Jeremy Long
d264d804c8 patches and test case update for issue #522 2016-07-05 09:09:58 -04:00
Jeremy Long
8272da615e improved test cases to debug issue #522 2016-07-04 08:43:43 -04:00
Jeremy Long
857b993d51 ensured analyzers were correctly initialized and closed 2016-07-04 07:55:53 -04:00
Jeremy Long
a71edf584e additional testing added 2016-07-04 07:55:19 -04:00
Jeremy Long
461d7fec0e fixed typo 2016-07-04 07:54:57 -04:00
Jeremy Long
5e3da035dd resolved merge conflict with #525 2016-07-04 07:11:45 -04:00
Jeremy Long
ebb52995a5 converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:10:07 -04:00
Jeremy Long
519b82c620 minor cleanup of code/comments 2016-07-04 07:07:07 -04:00
Jeremy Long
84682d07c6 converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:06:17 -04:00
Jeremy Long
960eeb19af converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:05:31 -04:00
Hans Joachim Desserud
ab3920f8f1 Replace raw Iterator with for each 2016-07-02 16:29:32 +02:00
Hans Joachim Desserud
f5f5857897 Add missing @Overrides 2016-07-02 16:23:24 +02:00
Hans Joachim Desserud
1c400b410e Remove unused imports 2016-07-02 16:23:16 +02:00
Jeremy Long
cc751aa224 updated to skip custom scripts in executable scripts 2016-06-27 19:39:17 -04:00
Jeremy Long
c20892ee3e removed stack traces from build 2016-06-27 08:46:46 -04:00
Jeremy Long
32ab53c9e1 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-06-26 07:32:23 -04:00
Jeremy Long
d0a7d9eb42 added test for issue #454 to ensure fully executable jar 2016-06-26 07:32:10 -04:00
Jeremy Long
a1a9602509 added support for fully executable jar files per issue #454 2016-06-26 07:31:17 -04:00
Jeremy Long
cf97c89fe0 fully exectuable jar for testing resolution for issue #454 2016-06-26 07:30:39 -04:00
Jeremy Long
8895bc85ea Merge pull request #521 from awhitford/Upg20160624
Plugin and Dependency Upgrades
2016-06-25 06:53:49 -04:00
Anthony Whitford
1a9976c6ca commons-compress 1.12, maven-jar-plugin 3.0.2, maven-source-plugin 3.0.1, maven-javadoc-plugin 2.10.4. 2016-06-24 23:51:12 -07:00
Anthony Whitford
f47ebf6145 jMockit 1.24, jSoup 1.9.2. 2016-06-24 23:35:24 -07:00
Jeremy Long
0380715311 resolved issue #514 2016-06-24 07:09:10 -04:00
Jeremy Long
80ad16c7fa updated to correctly label groovy's dependency scope 2016-06-22 06:48:11 -04:00
Jeremy Long
e56e9035b6 updated to correctly label groovy's dependency scope 2016-06-22 06:38:10 -04:00
Jeremy Long
73f22d32d2 fixed typo 2016-06-22 06:34:50 -04:00
Jeremy Long
c3bc56eebc additional suppressions 2016-06-18 07:33:30 -04:00
Jeremy Long
35cc14815e added property to solve issue #500 2016-06-18 07:32:57 -04:00
Jeremy Long
9be91474f6 staging 2016-06-18 06:46:28 -04:00
Jeremy Long
adf949bf08 added logging of URL 2016-06-18 06:18:16 -04:00
Jeremy Long
c6bf41b8ba staging 2016-06-18 06:17:55 -04:00
Jeremy Long
bc656c6218 version 1.4.0 2016-06-16 06:49:24 -04:00
Jeremy Long
f46226d055 updated documentation 2016-06-16 06:49:07 -04:00
bjiang
00d4ee47de merge upstream 2016-06-15 13:54:49 -04:00
Jeremy Long
c5ffc21660 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-06-15 06:51:18 -04:00
Jeremy Long
d89b1fdc6a updated proxy configuration information 2016-06-15 06:51:05 -04:00
Jeremy Long
8324287bd6 updated proxy configuration information 2016-06-15 06:50:45 -04:00
Jeremy Long
6be161a546 updated experimental documentation 2016-06-15 06:19:06 -04:00
Jeremy Long
027350e1ba Merge pull request #516 from msrb/weightings-bug
Correctly apply weightings when searching for CPEs
2016-06-15 05:48:55 -04:00
Michal Srb
a2309e1c2e Correctly apply weightings when searching for CPEs 2016-06-14 21:34:04 +02:00
Jeremy Long
c34dc97bd4 updated snapshot version 2016-06-11 08:13:14 -04:00
Jeremy Long
7e8749146e updated documentation 2016-06-11 08:12:09 -04:00
Jeremy Long
8680ecd033 updated documentation for experimental analyzers 2016-06-08 06:40:07 -04:00
Jeremy Long
4e4417c7af checkstyle corrections 2016-06-06 18:45:39 -04:00
Jeremy Long
7909bbbbe9 corrected remaining merge conflicts that were missed earlier as they were in comments 2016-06-06 06:45:33 -04:00
Jeremy Long
6fd831e688 corrected JavaDoc links 2016-06-06 06:44:42 -04:00
Jeremy Long
59a4825c70 added license 2016-06-05 17:40:42 -04:00
Jeremy Long
1ba3681457 updated the ci 2016-06-05 17:32:57 -04:00
Jeremy Long
78becffb2e updated CI build status url 2016-06-05 17:29:29 -04:00
Jeremy Long
e7efd7070b Merge pull request #508 from albuch/h2-clean-orphans
Thanks for the PR!
2016-06-05 17:25:53 -04:00
Jeremy Long
ec6471e8c7 added notes for future enhancment 2016-06-05 17:17:38 -04:00
Jeremy Long
b01ae2c6d3 updated to speed-up the unit test 2016-06-05 17:16:43 -04:00
Jeremy Long
ef4a260615 fixed build issue with CveDB being closed before saving the property 2016-06-05 17:16:05 -04:00
Jeremy Long
f6b80630dd temporary travis debugging code 2016-06-05 08:30:22 -04:00
Jeremy Long
f43589589d fixed setup to call super 2016-06-05 08:04:45 -04:00
Jeremy Long
06b59cf79b initial 2016-06-05 07:49:59 -04:00
Jeremy Long
a2187205e0 only update last checked after updates were performed without errors 2016-06-05 06:45:13 -04:00
Jeremy Long
52f269a289 Merge branch 'jabbrwcky-batch-update' 2016-06-05 06:33:45 -04:00
Jeremy Long
310ca967a1 fixed compareTo in order to resolve issue #503 2016-06-05 06:32:49 -04:00
Jeremy Long
c4b423cb0f additional tests resources to fix issue #503 2016-06-05 06:32:11 -04:00
Alexander v. Buchholtz
8a6c940aaf Optimized CLEANUP_ORPHANS query for H2 1.4.x
Original query from dbStatements.properties writes millions of records from subselect to file system due to MAX_MEMORY_ROWS Setting http://www.h2database.com/html/grammar.html?highlight=max_memory_rows&search=MAX_MEM#set_max_memory_rows
Database maintenance task therefore takes forever.
The new query (copied from postgresql) works way faster.
2016-06-04 23:36:43 +02:00
Jeremy Long
b295e927b7 resolved merge conflict 2016-06-04 09:09:57 -04:00
Jeremy Long
63d24737dd Merge pull request #506 from jabbrwcky/issue-503
Thanks for the test cases
2016-06-04 07:47:44 -04:00
Jeremy Long
60ce02ba28 improved logging to assist in resoloving issue #503 2016-06-04 07:46:42 -04:00
Jeremy Long
95939ed66c added javadoc per checkstyle 2016-06-04 07:45:07 -04:00
Jeremy Long
7f609a35be added javadoc per checkstyle 2016-06-04 07:44:42 -04:00
Jeremy Long
f7b534f1ee checkstyle correction 2016-06-04 07:44:08 -04:00
Jeremy Long
cd5f9e2f13 findbugs correction 2016-06-04 07:42:58 -04:00
Jens Hausherr
e79da72711 Use batch update for references and vulnerable software if supported by DB. 2016-06-03 10:22:54 +02:00
Jens Hausherr
1ba081959b Accidentially dropped some imports 2016-06-03 10:09:28 +02:00
Jens Hausherr
578dc63652 Vulnerable Software: Compact toString() output; remove accessor calls for own properties 2016-06-03 09:54:25 +02:00
Jens Hausherr
fccd683b50 add toString() for Vulnerability 2016-06-03 09:52:35 +02:00
Jens Hausherr
f3d3a25856 Add more test cases 2016-06-03 09:50:28 +02:00
Jens Hausherr
6d70c92795 Add to String-Method to Reference 2016-06-03 09:41:48 +02:00
Jeremy Long
3c525d8e3a fixed issue #505 2016-06-02 19:30:38 -04:00
Jeremy Long
a6b47c7c43 clarified note 2016-06-02 19:23:51 -04:00
Jeremy Long
5b52f01f3d updated documentation for issue#498 2016-05-30 08:23:58 -04:00
Jeremy Long
d13bbd43f3 added experimental flag to force users to enable this and by doing so understand that these may not be as production ready as the Java analyzer (see issue #498) 2016-05-30 08:09:14 -04:00
Jeremy Long
0394d1a24f checkstyle correction - reduced method length 2016-05-30 07:59:53 -04:00
Jeremy Long
446222e127 removed unnecessary exclude 2016-05-30 07:59:18 -04:00
Jeremy Long
05d7aa898d minor reformatting to reduce line length (checkstyle) 2016-05-30 07:37:44 -04:00
Jeremy Long
73f7fc1d51 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-05-30 07:19:15 -04:00
Jeremy Long
f0262466d4 Merge pull request #504 from awhitford/Upg052816
Plugin updates
2016-05-30 07:19:17 -04:00
Anthony Whitford
1ecde9bbc1 maven-jar-plugin 3.0.0 released; maven-resources-plugin 3.0.0 released. 2016-05-28 08:27:39 -07:00
Jens Hausherr
ae5a766092 Limit split to fix #503 2016-05-27 15:07:59 +02:00
Jeremy Long
6a807bc002 checkstyle/findbugs corrections 2016-05-25 17:21:46 -04:00
Jeremy Long
c0384bb0ee Merge pull request #502 from xthk/master
Update initialize_mysql.sql
2016-05-25 06:12:52 -04:00
Tilmann H
2906b315b3 Update initialize_mysql.sql
lower cased "properties" in UPDATE statement
2016-05-25 11:36:09 +02:00
Jeremy Long
425fd65bd8 added more false positive suppressions 2016-05-21 07:09:08 -04:00
Jeremy Long
7d83362a85 removed stack trace from build when ruby and bundle-audit are not installed 2016-05-15 07:49:17 -04:00
Jeremy Long
0b26894112 checkstyle/pmd/findbugs correction(s) 2016-05-15 07:48:26 -04:00
Jeremy Long
17f810a720 implement issue #498 2016-05-15 07:30:38 -04:00
Jeremy Long
71ef8061f9 merge conflict resolved 2016-05-15 07:29:17 -04:00
Jeremy Long
353b17690f checkstyle/pmd/findbugs correction(s) 2016-05-15 07:22:52 -04:00
Jeremy Long
6790727260 ensured resources are properly closed 2016-05-15 07:02:18 -04:00
Jeremy Long
e129f7db85 Merge branch 'biancajiang-ruby_dependency' 2016-05-15 06:46:18 -04:00
Jeremy Long
ea942398e3 updated test case to use the correct parent class that allows for use of the database during testing 2016-05-15 06:45:57 -04:00
Jeremy Long
5ad72cae3f Merge branch 'ruby_dependency' of git://github.com/biancajiang/DependencyCheck into biancajiang-ruby_dependency 2016-05-14 09:45:26 -04:00
Jeremy Long
5f945bc696 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-05-14 07:21:07 -04:00
Jeremy Long
6f451736ba Add ability to flag analyzers as experimental so that they are not always enabled 2016-05-14 07:20:53 -04:00
Jeremy Long
30856f4a4f corrected doxia version 2016-05-14 07:19:12 -04:00
bjiang
413c71eb0a Merge branch 'ruby_dependency' into swift_support 2016-05-13 13:49:40 -04:00
bjiang
9d1408be20 do not use actual path for packagePath from compress case 2016-05-13 13:33:34 -04:00
Jeremy Long
f21f371751 Merge pull request #494 from erikerikson/master
Align documentation with current project name specification flag
2016-05-06 18:23:32 -04:00
bjiang
2b761279e4 Merge branch 'ruby_dependency' into swift_support 2016-05-06 17:59:28 -04:00
bjiang
d5e8f54214 fix RubyBundlerAnalyzer.accept 2016-05-06 17:55:21 -04:00
bjiang
83f83d4eee add RubyBundlerAnalyzerTest 2016-05-06 17:45:40 -04:00
bjiang
b0f4ab9ba5 cleanup & Rakefile support placeholder 2016-05-06 17:25:08 -04:00
bjiang
06dad8f79c javadoc 2016-05-06 17:22:39 -04:00
bjiang
83ab122ddf disable RubyBundlerAnalyzer if RubyBundleAuditAnalyzer 2016-05-06 16:42:39 -04:00
bjiang
8a42fe4ae1 javadoc 2016-05-06 16:19:59 -04:00
bjiang
94c6778b89 better javadoc 2016-05-06 16:14:16 -04:00
bjiang
c0e5973517 rename RubyBundlerAnalyzer and javadoc 2016-05-06 15:50:35 -04:00
bjiang
1e7bbfa7c1 bundle the same SWIFT package by different analyzers 2016-05-06 13:43:05 -04:00
bjiang
dc7245ff6e code cleanup 2016-05-06 12:55:59 -04:00
bjiang
ffaf7b40e9 merge from ruby_dependency 2016-05-06 10:31:17 -04:00
bjiang
4de3fb1f2a javadoc 2016-05-06 10:25:49 -04:00
bjiang
99355d993a code cleanup with more comments 2016-05-06 10:24:28 -04:00
bjiang
d25f6e813c new analyzer for Package.swift 2016-05-05 19:21:21 -04:00
bjiang
043f8e0523 cleanup 2016-05-03 15:45:08 -04:00
bjiang
5fcf2a2623 get authors field 2016-05-03 14:53:25 -04:00
Erik Erikson
ee77fccffd Align documentation with current project name specification flag
When using the "--app" flag, the following warning is produced:

 [WARN] The 'app' argument should no longer be used; use 'project' instead.

 This change updates the documentation from suggesting "--app" to "--project"
2016-05-03 10:31:00 -07:00
bjiang
f1422adf75 merge upstream 2016-05-03 13:12:05 -04:00
bjiang
189da08885 merge upstream 2016-05-03 13:05:56 -04:00
bjiang
c2b1742582 support cocoapods for swift 2016-05-03 12:41:39 -04:00
Jeremy Long
9e63ac6d5b Merge pull request #493 from awhitford/CommIO25
Commons-IO 2.5 upgrade
2016-05-02 19:26:52 -04:00
Jeremy Long
4d7ab8b187 Merge pull request #491 from mwieczorek/MSSQL_Support
MSSQL Support
2016-05-02 19:25:39 -04:00
Jeremy Long
4de9818bee original CVE used in test does not exist in the current default DB used for tests. 2016-05-01 20:16:30 -04:00
Jeremy Long
7a2e1fd221 updated bundle audit score to be more accurate 2016-05-01 15:39:12 -04:00
Jeremy Long
d0ca800a23 Merge branch 'geramirez-fix-cvss-for-bundle-audit' 2016-04-30 11:20:39 -04:00
Jeremy Long
35ffd56ea9 fixed compile issues in PR 2016-04-30 11:20:26 -04:00
Jeremy Long
84b992d3a1 Merge branch 'fix-cvss-for-bundle-audit' of git://github.com/geramirez/DependencyCheck into geramirez-fix-cvss-for-bundle-audit 2016-04-30 11:02:16 -04:00
Jeremy Long
9e46364759 updated test cases to track down build issue 2016-04-30 10:56:50 -04:00
Dave Goddard
0f37c2b59c Adding sinatra fixture
Signed-off-by: Gabriel Ramirez <gabriel.e.ramirez@gmail.com>
2016-04-29 16:17:51 -04:00
Michal Wieczorek
33852ea7e3 MSSQL Support 2016-04-27 23:35:05 +02:00
Anthony Whitford
4fbed1cdac Added Charset to avoid deprecated FileUtils methods. 2016-04-27 01:37:00 -07:00
Anthony Whitford
42c61ab457 commons-io 2.5 released; jsoup 1.9.1 released. 2016-04-27 01:22:20 -07:00
David Jahn
8c6b9f9c68 Fixed CVSS for Ruby.
this bug was discovered when scanning ruby applications and getting back
`-1` cvss. this turns out to be a problem with bundle-audit cve
database.

Our solution was to use the NVD database, which dependency check uses to
get the CVSS scores for Ruby only if the Criticality is missing from
bundle-audit output. Keep in mind there are compilation errors with the
commit atm.

Fixes #485

Signed-off-by: Gabriel Ramirez <gabriel.e.ramirez@gmail.com>
2016-04-25 09:40:54 -04:00
Jeremy Long
abebecac4a updated parser and tests to revert to old suppression schema if new schema fails 2016-04-24 09:06:00 -04:00
Jeremy Long
87efe429da fixed broken schema 2016-04-24 09:05:26 -04:00
Jeremy Long
35128b0bd4 updated 2016-04-24 09:04:22 -04:00
Jeremy Long
186cb2270f ensure updated schema is published to the site 2016-04-24 07:25:32 -04:00
Jeremy Long
deda02f879 updated suppression schema to require a CPE, CVE, or CVSS Below per issue #488 2016-04-24 07:20:11 -04:00
Jeremy Long
bcc2478ef7 snapshot version 2016-04-24 07:17:42 -04:00
Jeremy Long
8d54654482 Merge pull request #487 from awhitford/DepUpg160416
Upgraded plugins and dependencies
2016-04-17 21:02:54 -04:00
Jeremy Long
08318107c1 Merge pull request #486 from awhitford/MavenWarnings
Maven warnings
2016-04-17 21:02:35 -04:00
Anthony Whitford
a5e77c85a6 Maven Site Plugin 3.5.1, Doxia 1.7.1, Ant 1.9.7, Maven 3.3.9. 2016-04-16 11:21:24 -07:00
Anthony Whitford
1e8d2aff75 Added code to avoid an unchecked cast warning. 2016-04-16 11:08:13 -07:00
Anthony Whitford
bc0a0f9902 Added missing serialVersionUID. 2016-04-16 11:07:19 -07:00
bjiang
da82f975e4 Add test for project url from pom.xml 2016-04-15 12:30:14 -04:00
bjiang
48af120db8 add project URL evidence from pom 2016-04-15 11:28:33 -04:00
Jeremy Long
8722eae766 version 1.3.6 2016-04-10 07:06:07 -04:00
Jeremy Long
53776936ca fix FP per issue #469 2016-04-09 11:27:08 -04:00
Jeremy Long
dca465b801 fixed minor warning about file encoding during build 2016-04-09 07:31:40 -04:00
Jeremy Long
43cd115dc7 Merge pull request #482 from awhitford/DepUpg-160406
Dependency Updates
2016-04-09 06:59:29 -04:00
Jeremy Long
e7ba08e52c updated log message to assist in debugging an issue 2016-04-09 06:51:00 -04:00
Jeremy Long
9df12e6ff2 updated log message to assist in debugging an issue 2016-04-09 06:49:44 -04:00
Jeremy Long
b5c7fb747c updated log message to assist in debugging an issue 2016-04-09 06:38:37 -04:00
Anthony Whitford
a40a4afe80 SLF4J 1.7.21 released; commons-compress 1.11 released. 2016-04-06 21:39:27 -07:00
bjiang
739f595f13 improve python package identification 2016-04-05 16:12:14 -04:00
bjiang
e07e892969 Merge branch 'master' into ruby_dependency 2016-04-05 14:47:17 -04:00
Jeremy Long
d4a6c58cc8 upgrade the transitive dependency commons-collections 2016-04-05 12:08:16 -04:00
Jeremy Long
d644431a4e Merge pull request #479 from awhitford/SLF4J1720LB117
SLF4J 1.7.20 and Logback 1.1.7 released.
2016-04-03 07:41:54 -04:00
bjiang
33bbb50b43 Ruby .gemspec must before bundler analyzer to get proper package grouping 2016-04-02 13:51:15 -04:00
bjiang
f89d7df305 improve vendor evidences for .gemspec analyzer 2016-04-02 13:49:50 -04:00
bjiang
3b02cd0e39 bundling same Ruby packages from .gemspec and bundler analyzers 2016-04-02 13:48:25 -04:00
bjiang
52cd50e0a8 keep delimitor space in array value 2016-04-01 14:08:41 -04:00
bjiang
996a970081 fix version evidence name 2016-04-01 14:07:03 -04:00
bjiang
6c0b65acd4 capture licenses and homepage in Ruby bundler analyzer 2016-04-01 13:30:36 -04:00
Anthony Whitford
f4df263dfe SLF4J 1.7.20 and Logback 1.1.7 released. 2016-03-30 21:03:51 -07:00
bjiang
8c659acc82 new Ruby bundler analyzer 2016-03-30 20:20:10 -04:00
bjiang
7aba2429af merge from upstream 2016-03-28 14:23:09 -04:00
bjiang
ab48d2c2ff multiple improvements 2016-03-28 14:06:30 -04:00
Jeremy Long
0b699d45bf Merge pull request #467 from colezlaw/python-init
Patch for jeremylong/DependencyCheck/#466
2016-03-25 19:35:06 -04:00
Jeremy Long
54beafa262 Merge pull request #475 from biancajiang/master
Fix test to skip the proper test case when bundle-audit is not available
2016-03-25 19:34:34 -04:00
Jeremy Long
531d4923eb Merge pull request #470 from MrBerg/suppress-osvdb
Make it possible to suppress vulnerabilities from OSVDB
2016-03-25 19:33:43 -04:00
Jeremy Long
b160a4d1dd Merge pull request #478 from swapnilsm/master
Added primary key to "software" table
2016-03-25 19:32:45 -04:00
Swapnil S. Mahajan
ca54daf456 Added primary key to "software" table
"software" is a bridge table so there should always be only one record for a pair of cpeEntryId and cveid.
2016-03-25 16:55:53 +05:30
bjiang
a22fc550b3 #472 fix test to only skip the proper test case. 2016-03-21 11:38:52 -04:00
Jeremy Long
0650d93953 Merge pull request #474 from awhitford/SLF4J1719
SLF4J 1.7.19 released.
2016-03-21 08:18:41 -04:00
Jeremy Long
5633258fa7 Update README.md 2016-03-21 08:16:06 -04:00
Jeremy Long
12278cda58 Update README.md
Fixed broken link to documentation.
2016-03-21 08:12:39 -04:00
Jeremy Long
84d1f08fda updated documentation for NVD urls to match what is hosted by NIST 2016-03-21 07:58:02 -04:00
Jeremy Long
c184292a57 Merge pull request #473 from biancajiang/master
Handle bundle-audit not available case and fix RubyBundleAuditAnalyzer test cases
2016-03-21 07:52:17 -04:00
Anthony Whitford
4cdfcb9f9d SLF4J 1.7.19 released. 2016-03-20 20:47:07 -04:00
bjiang
343a78917c Fixed #472. Disable RubyBundleAuditAnalyzer if exception during initialize.
changes:
1. disable self during initialize before bubbling exception
2. new test case RubyBundleAuditAnalyzerTest#testMissingBundleAudit()
2016-03-20 17:06:03 -04:00
bjiang
ff7d0fdb9d #472 first fix and improve RubyBundleAuditAnalyzerTest.java
Test were failing b/c Gemfile.lock and Gemfile were missing.
The files were missing b/c parent .gitignore them.
Changes:
1. Force added new test files, and updated test with more result
validation.
2. Added error logging from bundle-audit.
3. place holder for bundle-audit install directory in test
dependencycheck.properties.
2016-03-20 15:54:24 -04:00
Jonas Berg
db26b46be0 Make it possible to suppress vulnerabilities from OSVDB 2016-03-16 13:59:23 +02:00
Will Stranathan
d77a70c360 Patch for jeremylong/DependencyCheck/#466
This does two things:
1) Updates the PythonPackageAnalyzer to HIGH evidence for __init__.py
2) Removes evidence from the FileNameAnalyzer for __init__.py[co]?

TODO: Need for the PythonPackageAnalyzer to still add evidence for
__init__.py[co] even though it won't be able to analyze the contents of
it. Also, need to work up the tree for __init__.py files to get the
parent folders (not sure why subfolders are not being inspected).
2016-03-12 15:09:43 -05:00
Jeremy Long
42f4ae65d1 Merge pull request #463 from chadjvw/master
Updated Oracle init script
2016-03-07 20:43:05 -05:00
Chad Van Wyhe
88daac31d2 Merge pull request #1 from chadjvw/oracle-init-fix
fixed trigger compilation and added version number
2016-03-07 12:59:02 -06:00
Chad Van Wyhe
ac04c173a8 fixed trigger compilation and added version number 2016-03-07 12:55:18 -06:00
Jeremy Long
8401494fbc Merge pull request #462 from thc202/issues-page-gradle-purge
Fix issues in Gradle's dependencyCheckPurge task site page
2016-03-06 18:54:03 -05:00
Jeremy Long
97af118cb9 Merge pull request #461 from thc202/broken-link-readme
Fix broken link in README.md file... Thanks!
2016-03-06 18:53:12 -05:00
thc202
091e6026bc Fix issues in Gradle's dependencyCheckPurge task site page
Fix broken link to dependencyCheckUpdate task page, remove repeated
closing character ']'.
Replace $H with # in the heading of the example.
2016-03-06 23:46:12 +00:00
thc202
c798ede7bf Fix broken link in README.md file
Correct the link to NOTICE.txt file, change from NOTICES.txt to
NOTICE.txt.
2016-03-06 23:46:04 +00:00
Jeremy Long
225851f067 Merge pull request #460 from awhitford/DepUpg160306
Dependency Upgrades
2016-03-06 18:01:03 -05:00
Jeremy Long
9dd65ecf70 Merge pull request #459 from awhitford/MPIR29
maven-project-info-reports-plugin 2.9 released.
2016-03-06 18:00:48 -05:00
Jeremy Long
1a9cc4b6be snapshot 2016-03-06 17:42:18 -05:00
Jeremy Long
a612f206bf version 1.3.5.1 2016-03-06 17:30:37 -05:00
Jeremy Long
e51031c62a fix bug in getLastProject for non-site executions 2016-03-06 17:28:40 -05:00
Anthony Whitford
e30c29ef50 SLF4J 1.7.18 released; Logback 1.1.6 released; jMockit 1.22 released. 2016-03-06 08:53:58 -08:00
Anthony Whitford
91ddcadbcd Removed maven-site-plugin from dependencyManagement. 2016-03-06 08:51:04 -08:00
Anthony Whitford
8c145860e5 maven-project-info-reports-plugin 2.9 released. 2016-03-06 08:35:09 -08:00
Jeremy Long
a19dd7687e v 1.3.6-SNAPSHOT 2016-03-05 16:13:29 -05:00
Jeremy Long
550d6ca083 v1.3.5 2016-03-05 16:08:59 -05:00
Jeremy Long
b425411357 doclint fixes 2016-03-05 13:18:42 -05:00
Jeremy Long
a1f0cf749d doclint fixes 2016-03-05 13:18:38 -05:00
Jeremy Long
22e0d1c74e doclint fixes 2016-03-05 13:18:37 -05:00
Jeremy Long
cdc07047aa doclint fixes 2016-03-05 13:18:37 -05:00
Jeremy Long
c832c2da28 doclint fixes 2016-03-05 13:18:37 -05:00
Jeremy Long
8daa713639 doclint fixes 2016-03-05 13:18:36 -05:00
Jeremy Long
e0a2966706 doclint fixes 2016-03-05 13:18:36 -05:00
Jeremy Long
354bfa14f9 doclint fixes 2016-03-05 13:18:35 -05:00
Jeremy Long
46b91702ba doclint fixes 2016-03-05 13:18:35 -05:00
Jeremy Long
de9516e368 doclint fixes 2016-03-05 13:18:35 -05:00
Jeremy Long
3924e07e5c doclint fixes 2016-03-05 13:18:34 -05:00
Jeremy Long
76bcbb5a7e doclint fixes 2016-03-05 13:18:34 -05:00
Jeremy Long
8022381d1c doclint fixes 2016-03-05 13:18:33 -05:00
Jeremy Long
feb1233081 doclint fixes 2016-03-05 13:18:33 -05:00
Jeremy Long
36eefd0836 doclint fixes 2016-03-05 13:18:32 -05:00
Jeremy Long
0e31e59759 doclint fixes 2016-03-05 13:18:32 -05:00
Jeremy Long
4a4c1e75da doclint fixes 2016-03-05 13:18:32 -05:00
Jeremy Long
b0bfd2292a doclint fixes 2016-03-05 13:18:31 -05:00
Jeremy Long
7214b24357 doclint fixes 2016-03-05 13:18:31 -05:00
Jeremy Long
24637f496f doclint fixes 2016-03-05 13:18:30 -05:00
Jeremy Long
d8ecde5265 doclint fixes 2016-03-05 13:18:30 -05:00
Jeremy Long
28840c6209 doclint fixes 2016-03-05 13:18:29 -05:00
Jeremy Long
1696213406 doclint fixes 2016-03-05 13:18:29 -05:00
Jeremy Long
6f315ac765 doclint fixes 2016-03-05 13:18:28 -05:00
Jeremy Long
a485307d92 doclint fixes 2016-03-05 13:18:28 -05:00
Jeremy Long
3d3b861ba0 doclint fixes 2016-03-05 13:18:28 -05:00
Jeremy Long
4b33ed25d5 doclint fixes 2016-03-05 13:18:27 -05:00
Jeremy Long
e264880c7b doclint fixes 2016-03-05 13:18:27 -05:00
Jeremy Long
ef8212701f doclint fixes 2016-03-05 13:18:26 -05:00
Jeremy Long
492157a502 doclint fixes 2016-03-05 13:18:26 -05:00
Jeremy Long
2605bc182e doclint fixes 2016-03-05 13:18:25 -05:00
Jeremy Long
fe8dfdd804 doclint fixes 2016-03-05 13:18:25 -05:00
Jeremy Long
bd917bc990 doclint fixes 2016-03-05 13:18:24 -05:00
Jeremy Long
c5c32f683f doclint fixes 2016-03-05 13:18:24 -05:00
Jeremy Long
5506e58c98 doclint fixes 2016-03-05 13:18:23 -05:00
Jeremy Long
5af2d49b18 doclint fixes 2016-03-05 13:18:23 -05:00
Jeremy Long
0fd35a4925 doclint fixes 2016-03-05 13:18:23 -05:00
Jeremy Long
7ed20b1244 doclint fixes 2016-03-05 13:18:22 -05:00
Jeremy Long
efa6a78255 doclint fixes 2016-03-05 13:18:22 -05:00
Jeremy Long
8b58df3b34 checkstyle/pmd/findbugs corrections 2016-03-05 07:07:53 -05:00
Jeremy Long
0d2a090e1f Merge pull request #456 from awhitford/Site35
Upgrade for Maven Site Plugin 3.5
2016-03-04 17:42:14 -05:00
Jeremy Long
7860d635a9 ensured deserialization is secure 2016-03-04 17:38:48 -05:00
Anthony Whitford
ba91c9fa9b Upgraded maven site plugin to 3.5, and doxia markdown module to 1.7. 2016-02-28 09:34:19 -08:00
Anthony Whitford
b3630e0d5e Upgraded the Fluido 1.5 skin and had to update site head for maven site plugin 3.5. See http://maven.apache.org/plugins/maven-site-plugin/examples/sitedescriptor.html#Inject_xhtml_into_head 2016-02-28 09:33:54 -08:00
Jeremy Long
f752285912 added test for parse manifest per issue #455 2016-02-27 07:14:27 -05:00
Jeremy Long
5a150d9b0e parsed additional entries in the manifest per issue #455 2016-02-27 07:13:57 -05:00
Jeremy Long
f0aa185832 added test dependency per issue #455 2016-02-27 07:12:30 -05:00
Jeremy Long
9592f058d4 add more false positives to the suppression list 2016-02-25 18:01:21 -05:00
Jeremy Long
f630794e22 added warning about site:stage with regards to the aggregate goal 2016-02-24 17:00:31 -05:00
Jeremy Long
93636e89c5 fixed broken hyperlinks 2016-02-23 20:54:24 -05:00
Jeremy Long
585002c25c resolution for issue #386 fixed the conditional so that execution occured on the last non-skipped project in the reactor 2016-02-23 20:42:10 -05:00
Jeremy Long
412ccc1be1 per issue #429 updates will only occur if the database schema and expected schema match exactly 2016-02-21 08:38:29 -05:00
Jeremy Long
8b1306a36c per issue #429 non-h2 databases may be used as long as the database schema is of the same major version and greater then or equal to the expected version. 2016-02-21 08:11:29 -05:00
Jeremy Long
81026e8dca isolate the analyze method to try and resolve multiple threads hitting the Lucene query parsers at the same time per issue #388 2016-02-20 08:18:00 -05:00
Jeremy Long
dd440c8f9f resolve issue #451 2016-02-20 08:12:14 -05:00
Jeremy Long
76f3e4b27e Merge pull request #449 from christiangalsterer/i444
Support nonProxyHosts parameter in settings.xml #444
2016-02-17 19:09:41 -05:00
Jeremy Long
5f5d3fdb66 Merge pull request #447 from kaimago/master
Oracle DB Support
2016-02-17 19:06:13 -05:00
Jeremy Long
853c92b87d Merge pull request #448 from awhitford/UpgFeb6-16
Upgraded SLF4J to 1.7.14 and the maven-compiler-plugin to 3.5.
2016-02-17 19:03:37 -05:00
Anthony Whitford
00080f2abc SLF4J 1.7.16 released; logback 1.1.5 released. 2016-02-15 10:23:07 -08:00
Anthony Whitford
55414208a3 SLF4J 1.7.15 released; maven-compiler-plugin 3.5.1 released. 2016-02-10 00:34:26 -08:00
Christian Galsterer
5091499563 [i444] Support nonProxyHosts parameter in settings.xml 2016-02-09 18:01:36 +01:00
Anthony Whitford
944b54d920 Upgraded SLF4J to 1.7.14 and the maven-compiler-plugin to 3.5. 2016-02-06 12:14:19 -08:00
Christian Galsterer
d023b2b2ff [i444] Support nonProxyHosts parameter in settings.xml 2016-02-06 16:13:01 +01:00
Jeremy Long
b45f9f514b base test case handles settings initialization 2016-02-06 08:40:33 -05:00
Jeremy Long
239a9383e0 fix for issue #446 2016-02-06 08:30:06 -05:00
Jeremy Long
2190c0229c added check to see if the file is xml prior to unzipping it per issue #441 2016-02-06 08:11:24 -05:00
I003306
01ef14dc92 Oracle DB Support 2016-02-04 15:23:57 +01:00
Jeremy Long
7b0784843c updated copyright 2016-01-31 17:23:13 -05:00
Jeremy Long
6fc805369e snapshot version 2016-01-31 17:11:37 -05:00
Jeremy Long
9e29939cd3 version 1.3.4 2016-01-31 16:50:34 -05:00
Jeremy Long
d750abca22 resolved issue with new databases not being created correctly if there was an intial download of the NVD data. 2016-01-31 08:26:23 -05:00
Jeremy Long
31df2fa131 findbugs/checkstyle corrections 2016-01-30 08:57:40 -05:00
Jeremy Long
6355a29a7a updated version to ensure there are no issues in the jenkins plugin per issue #445 2016-01-30 08:07:33 -05:00
Jeremy Long
86a2b38340 Merge pull request #440 from awhitford/DepUpg20160110
Upgrades
2016-01-24 08:40:51 -05:00
Jeremy Long
9cb2b58557 initial fix for issue #445 2016-01-24 08:35:44 -05:00
Jeremy Long
2b0e2e8d0d corrected link per issuue #443 2016-01-17 08:08:15 -05:00
Jeremy Long
cf46767196 resolution for issue #439 2016-01-16 07:39:48 -05:00
Anthony Whitford
ffc1034b5a findbugs-maven-plugin 3.0.3 released; JavaMail api 1.5.5 released; jMockit 1.21 released. 2016-01-10 10:01:33 -08:00
Jeremy Long
46bb19de9b supression rules to resolve issues #437 and #438 2016-01-10 07:45:29 -05:00
Jeremy Long
70bc7a6d01 Merge pull request #435 from awhitford/Surefire-2.19.1
Upgraded Surefire to 2.19.1 release.
2016-01-10 07:01:08 -05:00
Anthony Whitford
3164505273 Upgraded Surefire to 2.19.1 release. 2016-01-05 08:12:32 -08:00
Jeremy Long
3d84fcd037 resolves issue #433 2016-01-03 09:18:35 -05:00
Jeremy Long
578fa32243 updated to honor noupdate flag for version check and removed some complexity 2016-01-03 09:14:08 -05:00
Jeremy Long
fc00b7d1cc resolves issues #426 2016-01-03 08:51:03 -05:00
Jeremy Long
d7351bd3e5 Merge pull request #432 from awhitford/CodeTweaks20151228
Code tweaks 2015-12-28
2016-01-03 08:33:16 -05:00
Anthony Whitford
e7224c8f05 StringBuilder allocation more precise. 2015-12-31 09:25:44 -08:00
Anthony Whitford
b97622f45b Variables may be final. 2015-12-28 13:15:24 -08:00
Anthony Whitford
0e15f3b703 Add missing final keyword to local variables. 2015-12-28 13:14:31 -08:00
Anthony Whitford
6604c0da89 Default StringBuilder size should be larger than default 16. 2015-12-28 13:14:04 -08:00
Anthony Whitford
e0b8be20b3 Variable suppressionRules may be final. 2015-12-28 13:13:33 -08:00
Anthony Whitford
46965d8c96 Iterable does not need qualifying, and collection may be final. 2015-12-28 13:13:00 -08:00
Anthony Whitford
66e92f00ee Variable may be final. 2015-12-28 13:12:10 -08:00
Anthony Whitford
4a137b4e8e Use StringBuilder instead of String += concatenation. 2015-12-28 13:11:36 -08:00
Anthony Whitford
9d5ff28098 Variables can be final and the exception was unused so can be removed. 2015-12-28 13:10:37 -08:00
Anthony Whitford
313b114da5 Variables can be final. 2015-12-28 13:09:17 -08:00
Anthony Whitford
1b6bfc6338 Variables can be final. 2015-12-28 13:08:37 -08:00
Anthony Whitford
49fd89f34a Let's use logging parameters for lazy evaluation. 2015-12-28 13:07:34 -08:00
Anthony Whitford
a2e862886e Rather than an explicit StringBuilder, why not simply an implicit one? 2015-12-28 13:06:44 -08:00
Anthony Whitford
62f6c7c5a9 Rather than using instanceOf, just add a specific catch for AnalysisException. 2015-12-28 13:05:45 -08:00
Jeremy Long
2294ed1ce1 Merge pull request #430 from awhitford/PluginUpdates20151227
Plugin updates
2015-12-28 06:12:54 -05:00
Jeremy Long
c8a1c6a318 fixed issue #431 - missing dependency 2015-12-28 06:11:57 -05:00
Anthony Whitford
600ed66d5b maven-clean-plugin 3.0.0 released; maven-source-plugin 2.4 released; maven-javadoc-plugin 2.10.3 released. 2015-12-27 11:45:52 -08:00
Jeremy Long
512b17555c updated documentation for encrypted passwords per issue #417 2015-12-26 12:55:41 -05:00
Jeremy Long
dc7849c9e8 added support for encrypted passwords per issue #417 2015-12-26 07:13:40 -05:00
Jeremy Long
6a99a51b91 Merge pull request #425 from awhitford/PluginUpdate20151220
maven-pmd-plugin 3.6 released.
2015-12-25 07:07:22 -05:00
Anthony Whitford
8c7fa022a0 maven-pmd-plugin 3.6 released. 2015-12-20 10:10:55 -08:00
Jeremy Long
cca694a580 logs from issue #138 indicate multiple modules are calling a non-threadsafe operation; as such, the mojo is being marked as threadSafe=false 2015-12-18 06:36:14 -05:00
Jeremy Long
3a7f95b9b1 spelling correction 2015-12-18 06:28:11 -05:00
Jeremy Long
3a84dc3962 fixed casing per issue #418 2015-12-18 06:05:01 -05:00
Jeremy Long
5961a96a4c Merge pull request #424 from amandel/patch-1
Fix casing of properties table name.
2015-12-18 05:55:04 -05:00
Jeremy Long
a22382505f Merge pull request #420 from awhitford/Issue419
Issue #419 - Avoiding a duplicate CPE Index Created message
2015-12-18 05:51:26 -05:00
Jeremy Long
5faef75415 Merge pull request #422 from edgedalmacio/patch-1
added tomcat suppressions
2015-12-18 05:49:16 -05:00
Jeremy Long
fed60907dc snapshot version 2015-12-18 05:48:37 -05:00
Andreas Mandel
ce7e360b70 If casing of properties table name. 2015-12-17 14:06:16 +01:00
Edge Dalmacio
0b3def38b8 added tomcat suppressions
tomcat-embed-el
tomcat-jdbc
tomcat-juli
2015-12-17 15:27:17 +08:00
Anthony Whitford
25a15dea8c Issue #419 - Avoiding a duplicate CPE Index Created message and resource leak. 2015-12-14 00:52:48 -08:00
Jeremy Long
e204971a6c version 1.3.3 2015-12-10 19:44:38 -05:00
Jeremy Long
d5b3a118bc minor site tweaks 2015-12-10 19:44:26 -05:00
Jeremy Long
3396cb2887 fix for issue #416 2015-12-10 18:33:31 -05:00
Jeremy Long
3c5beea218 1.3.3-SNAPSHOT 2015-12-02 09:17:28 -05:00
Jeremy Long
e544384dd5 1.3.3-SNAPSHOT 2015-12-02 05:46:28 -05:00
Jeremy Long
0e90f460f4 reverted change, using the undocumented SERIALIZED file lock mode 2015-12-02 05:46:06 -05:00
Jeremy Long
921efc4d2b updated documentation 2015-11-30 06:50:15 -05:00
Jeremy Long
1b3b4a5906 version 1.3.2 2015-11-29 07:34:45 -05:00
Jeremy Long
5c8b374352 updated documentation 2015-11-28 08:14:00 -05:00
Jeremy Long
e05cef6886 extended the wrong base test case 2015-11-27 07:07:17 -05:00
Jeremy Long
cb39ecacf9 moved dependency-check-gradle to a new repo 2015-11-27 06:54:48 -05:00
Jeremy Long
e6816f94eb moving documentation of gradle and jenkins plugins under the main parent site 2015-11-26 06:36:35 -05:00
Jeremy Long
8b5dbeab44 removed stack trace in build when bundle audit is not installed 2015-11-25 05:59:58 -05:00
Jeremy Long
29c21c3611 pmd/checkstyle/findbugs corrections 2015-11-25 05:43:04 -05:00
Jeremy Long
e05bed8d65 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-11-24 16:12:30 -05:00
Jeremy Long
1b2210aba0 pmd/checkstyle/findbugs corrections 2015-11-24 16:12:23 -05:00
Jeremy Long
7fb1b1d57b Merge pull request #330 from dwvisser/ruby-bundler
Ruby bundler-audit Analyzer
2015-11-24 15:53:00 -05:00
Jeremy Long
a3adf71a1d avoid npe 2015-11-24 05:43:45 -05:00
Jeremy Long
51d81fab5d grok assembly exe was hanging, reordered so input stream was processed before error stream to resolve the issue. 2015-11-24 05:34:34 -05:00
Dale Visser
2ed5dc153a Fixed merge conflict in App.java 2015-11-23 13:27:22 -05:00
Jeremy Long
5f8f156bee Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-11-22 07:31:27 -05:00
Jeremy Long
eb03c90d7a updated documentation 2015-11-22 07:31:17 -05:00
Jeremy Long
fc05471086 bug fix that might be related to #388, in addition added logging incase the bug fix does not work 2015-11-22 07:30:28 -05:00
Jeremy Long
b9db2dd89f Merge pull request #409 from awhitford/MinorCodeTweaks
Thanks!
2015-11-22 07:14:12 -05:00
Jeremy Long
de7fe21a4f Merge pull request #411 from hansjoachim/upgrade-slf4j
Upgraded slf4j to latest version
2015-11-22 07:07:07 -05:00
Jeremy Long
56f9a7c4f9 Merge pull request #407 from awhitford/DepUpg
Upgraded dependencies.
2015-11-22 07:06:38 -05:00
Hans Joachim Desserud
df569a5ae2 Upgraded slf4j to latest version 2015-11-14 10:10:44 +01:00
Jeremy Long
acb9d04c51 updated to be feature complete with 1.3.2-SNAPSHOT 2015-11-11 18:44:19 -05:00
Jeremy Long
09c4708a22 update for issue #410 2015-11-11 00:58:00 -05:00
Anthony Whitford
b346dfe0a3 Minor code tweaks. 2015-11-10 00:09:01 -08:00
Jeremy Long
5f259cb88c added missed configuration options for new analyzers 2015-11-07 06:37:36 -05:00
Anthony Whitford
fb2aff3310 Upgraded dependencies. 2015-11-06 23:16:12 -08:00
Jeremy Long
3c4c65c28c corrected NVD CVE URLs 2015-11-04 06:00:04 -05:00
Jeremy Long
15885e3e8c Merge branch 'awhitford-ModelInterpolationAlt' 2015-11-03 05:52:54 -05:00
Jeremy Long
5508c60e85 resulved conflict 2015-11-03 05:52:22 -05:00
Jeremy Long
ffc341e4b9 Merge pull request #405 from awhitford/StringToChar
One character String constants with char constants
2015-11-03 05:43:41 -05:00
Jeremy Long
41a68f7b25 Merge pull request #406 from awhitford/DropCountCharacters
Removed unnecessary countCharacter method.
2015-11-03 05:42:28 -05:00
Anthony Whitford
041d3c5312 Removed unnecessary countCharacter method by leveraging StringUtils.countMatches. 2015-11-01 23:19:37 -08:00
Anthony Whitford
8e8b462bc8 Replaced one character String constants with char constants, when applicable. 2015-11-01 22:39:30 -08:00
Jeremy Long
efbc76e06f Merge pull request #402 from awhitford/SettingsSetters
New setters for Settings
2015-11-01 05:52:34 -05:00
Jeremy Long
67a44d2adc added postgres 2015-11-01 05:50:08 -05:00
Anthony Whitford
92a35b929a Leveraged the new setters with null and empty checking for Settings. 2015-10-31 10:26:32 -07:00
Anthony Whitford
e5744dd63f Added extra setters with null and empty checks. 2015-10-31 10:25:50 -07:00
Jeremy Long
f2f3d050bd added 3.0 update schema 2015-10-31 07:25:02 -04:00
Jeremy Long
0cbecbe3a0 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-10-30 05:42:36 -04:00
Jeremy Long
51a8b5a058 added mysql dialect 2015-10-30 05:41:12 -04:00
Jeremy Long
aaf716e54b Merge pull request #395 from awhitford/IOUtils
Leverage IOUtils
2015-10-30 05:32:44 -04:00
Jeremy Long
209fcc7946 Merge pull request #397 from awhitford/ModelInterpolate
Improved interpolateString.
2015-10-30 05:31:35 -04:00
Jeremy Long
a5cb131806 Merge pull request #400 from kgeis/patch-1
Update index.md.vm
2015-10-30 05:23:09 -04:00
Ken Geis
8fbeb5f5d5 Update index.md.vm
update usage examples to match currently used flags (--app -> --project)
2015-10-28 09:26:59 -07:00
Anthony Whitford
a92bdfe30d Alternative interpolateString implementation leveraging commons-lang3. 2015-10-28 00:08:12 -07:00
Anthony Whitford
7f130ff036 Improved interpolateString. 2015-10-27 23:25:28 -07:00
Jeremy Long
b704f72854 fixed npe 2015-10-27 06:15:34 -04:00
Anthony Whitford
e21f8a97ac More opportunities to leverage IOUtils. 2015-10-27 01:00:29 -07:00
Anthony Whitford
a8ff403809 Removed unused imports. 2015-10-27 01:00:04 -07:00
Anthony Whitford
22097c0a25 Replaced boiler-plate file read with simpler IOUtils call. 2015-10-27 00:10:32 -07:00
Jeremy Long
92e7d9cf80 improved update failure reporting 2015-10-26 06:36:10 -04:00
Jeremy Long
54d921f275 added test case 2015-10-26 06:32:02 -04:00
Jeremy Long
08d7b3dbce currently unused but contains DDL that may be needed in the future 2015-10-26 06:31:43 -04:00
Jeremy Long
6949b3c229 update file cannot contain comments 2015-10-26 06:30:56 -04:00
Jeremy Long
b0ca38bd29 reverted surefire due to IDE integration failures with 2.19 2015-10-26 06:30:16 -04:00
Jeremy Long
cf173ee9e7 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-10-25 06:22:36 -04:00
Jeremy Long
aa9908b34a updated test properties w/ changes that had been made in the main properties 2015-10-25 06:22:30 -04:00
Jeremy Long
640674ef72 minor - added a comment explaining one of the preoperties 2015-10-25 06:21:48 -04:00
Jeremy Long
0c69ab80bb Merge pull request #382 from awhitford/MojoStreamClose
Removed unnecessary OutputStream closing.
2015-10-25 06:04:28 -04:00
Jeremy Long
662557c2f3 Merge pull request #387 from fabioscala/feature/overrideSuppressionFile
Allow setting suppression file in gradle plugin
2015-10-25 06:03:15 -04:00
Jeremy Long
346b2c31d2 moved default values to the properties file instead of hard-coding them 2015-10-25 05:58:57 -04:00
Jeremy Long
62dbf99557 moved default values to the properties file instead of hard-coding them 2015-10-25 05:57:24 -04:00
Jeremy Long
99b140adaa updated field name to make it more clear 2015-10-24 06:19:00 -04:00
Jeremy Long
387d577d4f updated field name to make it more clear 2015-10-24 06:18:36 -04:00
Jeremy Long
ab7eee7db9 updated field name to make it more clear 2015-10-24 06:18:09 -04:00
Jeremy Long
487a45f01b updated field name to make it more clear 2015-10-24 06:17:31 -04:00
Jeremy Long
60665c6bd8 Merge pull request #392 from awhitford/PluginUpgrades
Upgraded plugins.
2015-10-23 06:30:17 -04:00
Jeremy Long
8fc9a3d6d1 Merge pull request #391 from awhitford/CpeSetting
Change CpeUpdater to use CPE_MODIFIED_VALID_FOR_DAYS
2015-10-23 06:29:51 -04:00
Jeremy Long
05a05f7e88 Merge branch 'awhitford-NvdCheck' 2015-10-23 06:28:34 -04:00
Jeremy Long
0c5bdfd7b7 added a setInt in support of PR #390 2015-10-23 06:28:04 -04:00
Jeremy Long
626e93c7e3 minor changes to patch for PR #390 2015-10-23 06:27:29 -04:00
Jeremy Long
b588c4c900 set a default value of four hours for issue #390 2015-10-23 06:26:42 -04:00
Jeremy Long
c52a0d88df expanded issue #390 to the CLI 2015-10-23 06:25:47 -04:00
Jeremy Long
84838d19d9 added documentation for issue #390 2015-10-23 06:25:20 -04:00
Jeremy Long
faf335a181 expanded issue #390 to the Ant task 2015-10-23 06:24:14 -04:00
Jeremy Long
5c25351884 removed default value that over-wrote the properties file value 2015-10-23 06:22:58 -04:00
Jeremy Long
520f3cb09a Merge branch 'NvdCheck' of https://github.com/awhitford/DependencyCheck into awhitford-NvdCheck 2015-10-23 05:32:27 -04:00
Anthony Whitford
e234246618 Upgraded plugins. 2015-10-22 00:18:50 -07:00
Anthony Whitford
5d1d378f61 Shouldn't CPE Updater use the CPE_MODIFIED_VALID_FOR_DAYS setting (not CVE)? 2015-10-21 23:56:28 -07:00
Anthony Whitford
cef3bb7424 Reworked withinDateRange to avoid type conversion between doubles and longs; expressed in long integer math. 2015-10-21 23:27:03 -07:00
Anthony Whitford
ccb03f2763 Added cveValidForHours parameter that can suppress redundant and repetitive checks for NVD CVE changes. 2015-10-21 23:25:18 -07:00
Anthony Whitford
1f6168366b Added logic to optionally prevent overly repetitive checks for NVD CVE changes. 2015-10-21 23:23:47 -07:00
Anthony Whitford
cd5bf85245 Added a database property for recording the last time the NVD CVE was checked. 2015-10-21 23:21:25 -07:00
Anthony Whitford
f2778e5d28 Adding a setting to suppress repetitive NVD checks. 2015-10-21 23:19:57 -07:00
Jeremy Long
c2e6065ed7 added option to change the name of the report per issue #389 2015-10-20 06:18:28 -04:00
Jeremy Long
fccba5f7fd Merge pull request #381 from awhitford/SkipMojo
Added basic skip option for mojos.
2015-10-20 05:58:16 -04:00
Jeremy Long
3f230c5a05 resolve issue #372 2015-10-18 06:32:44 -04:00
Jeremy Long
dc849c3891 removed duplicate abstract test base 2015-10-18 06:17:21 -04:00
Jeremy Long
2770b58a20 fixing the build 2015-10-18 06:07:23 -04:00
Jeremy Long
37519acfb8 minor performance improvement 2015-10-17 07:42:09 -04:00
Jeremy Long
ad8c7b3cd2 missed one character in my lucene escape util 2015-10-17 07:40:38 -04:00
Jeremy Long
04db8d3208 Merge pull request #385 from awhitford/FileUtils
Leverage FilenameUtils
2015-10-16 06:30:53 -04:00
Jeremy Long
666e3b1e30 fix for issue #384 2015-10-16 06:23:03 -04:00
Fabio Scala
dc68781c06 Allow setting suppression file in gradle plugin 2015-10-15 11:24:33 +02:00
Jeremy Long
a7f50d147e depending on test order this test may fail if ArchiveAnalyzer was previously loaded. 2015-10-14 07:12:04 -04:00
Anthony Whitford
7e639db5de Leveraging FilenameUtils rather than string dissection. 2015-10-14 00:16:20 -07:00
Anthony Whitford
19a97a1706 Demonstrating the benefit of commons-io instead of the simpler string dissection. 2015-10-13 23:59:31 -07:00
Anthony Whitford
cd66a9ef61 Demonstrating the benefit of commons-io instead of the simpler string dissection. 2015-10-13 23:59:11 -07:00
Anthony Whitford
f121430a5d Simplified getFileExtension by leveraging commons-io. Also cut a line from delete. 2015-10-13 23:50:41 -07:00
Jeremy Long
2f518dacfc Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-10-13 21:24:22 -04:00
Jeremy Long
fded8b6cd3 fixed issue #383 2015-10-13 21:24:03 -04:00
Jeremy Long
3b6c64dc9d move test resource to correct directory 2015-10-13 19:03:33 -04:00
Jeremy Long
d742985640 resolve issue #377 2015-10-13 19:03:19 -04:00
Jeremy Long
a13dd58989 Merge pull request #380 from awhitford/TestLint
Removed compiler warnings from test code.
2015-10-12 06:46:50 -04:00
Jeremy Long
622b3210ae Merge pull request #379 from awhitford/HashSetLen
Sized the new HashSet to avoid rehashing risk.
2015-10-12 06:46:12 -04:00
Jeremy Long
90c97ed6aa Merge pull request #376 from awhitford/ComposerExSerial
Added missing serialVersionUID to new ComposerException.
2015-10-12 06:45:38 -04:00
Jeremy Long
53a4dfbf88 Merge pull request #378 from awhitford/RmNonCloseStream
Removing unused NonClosingStream.
2015-10-12 06:45:20 -04:00
Jeremy Long
f488c57363 Merge branch 'awhitford-DbMerge' 2015-10-12 06:44:00 -04:00
Jeremy Long
0ce830ca9d fixed test case to correctly initialize the settings 2015-10-12 06:43:32 -04:00
Jeremy Long
30ae418c2c updated MySQL profile 2015-10-12 06:42:55 -04:00
Jeremy Long
3b976d211f upgrdae db schema version 2015-10-12 06:15:24 -04:00
Jeremy Long
cca49b5dc2 added information regarding updating the database schema 2015-10-12 06:13:06 -04:00
Jeremy Long
8c2b2070c6 added URL to database upgrade page 2015-10-12 05:53:07 -04:00
Jeremy Long
24b8ff26db Merge branch 'DbMerge' of https://github.com/awhitford/DependencyCheck into awhitford-DbMerge 2015-10-12 05:48:03 -04:00
Jeremy Long
f0d93538ae changed update script to fail on non-H2 databases; they require manual upgrades 2015-10-12 05:47:50 -04:00
Jeremy Long
02eab65c4e upgrade h2 db schema to 3.0 2015-10-12 05:47:00 -04:00
Jeremy Long
d941aa7df3 script to upgrade a MySQL db 2015-10-12 05:46:33 -04:00
Anthony Whitford
b5026a45f6 Removed unnecessary OutputStream closing. Also the flush and reset are not necessary since the stream is being closed right away. 2015-10-11 19:09:03 -07:00
Anthony Whitford
79fde3ebc9 Added basic skip option for mojos. 2015-10-11 18:44:25 -07:00
Anthony Whitford
031d648585 Removed compiler warnings from test code. 2015-10-11 17:48:27 -07:00
Anthony Whitford
762b2fe7d6 Leverage Collections.singleton for single entry HashSets. 2015-10-11 17:32:08 -07:00
Anthony Whitford
5db377923e Sized the new HashSet to avoid rehashing risk. 2015-10-11 16:51:57 -07:00
Anthony Whitford
c3177df739 Removing unused NonClosingStream. 2015-10-11 11:42:03 -07:00
Anthony Whitford
0dc36765f1 Added missing serialVersionUID to new ComposerException. 2015-10-10 16:19:59 -07:00
Jeremy Long
38e61ebd8d Merge branch 'awhitford-MvnPhase' 2015-10-10 06:15:29 -04:00
Jeremy Long
529b9739b5 changed default phase to VERIFY 2015-10-10 06:14:50 -04:00
Jeremy Long
a014ca7d8a Merge branch 'MvnPhase' of https://github.com/awhitford/DependencyCheck into awhitford-MvnPhase 2015-10-10 05:59:04 -04:00
Jeremy Long
83701f7d0d Merge pull request #374 from awhitford/EngineScanTweak
Consolidated scan(Set) and scan(List) with scan(Collection).
2015-10-10 05:54:31 -04:00
Jeremy Long
b2500939f3 Merge pull request #375 from skitt/cme-fix
Avoid ConcurrentModificationExceptions
2015-10-10 05:52:32 -04:00
Stephen Kitt
1852b9dbb2 Avoid ConcurrentModificationExceptions
AggregateMojo.getDescendants() can end up adding descendants while
it's iterating over them. This separates the addition from the
iteration to avoid this.

Signed-off-by: Stephen Kitt <skitt@redhat.com>
2015-10-09 17:07:27 +02:00
Anthony Whitford
069474fc71 Consolidated scan(Set) and scan(List) with scan(Collection). 2015-10-09 07:52:43 -07:00
Jeremy Long
e7f518264a Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-10-09 08:52:06 -04:00
Jeremy Long
b0b096c3f5 updated version to 1.3.2-SNAPSHOT 2015-10-09 08:51:58 -04:00
Jeremy Long
bfa9d04d42 added another suppression rule 2015-10-09 08:33:04 -04:00
Jeremy Long
7dbe58469a Merge pull request #371 from awhitford/CpeLucenePerf
Re-use Document and Field instances to minimize GC overhead.
2015-10-09 07:03:35 -04:00
Jeremy Long
41b36dabc2 Merge pull request #370 from awhitford/DontLogToString
Do not need or want to call toString for a logger parameter.
2015-10-09 07:01:44 -04:00
Jeremy Long
4a685557d9 Merge pull request #369 from awhitford/BadSuppress
Removed unnecessary @SuppressWarnings.
2015-10-09 07:01:02 -04:00
Jeremy Long
e7ef4b6906 Merge pull request #367 from awhitford/SettingsCleanup
Settings cleanup
2015-10-09 07:00:39 -04:00
Jeremy Long
67502fb9d3 Merge pull request #368 from awhitford/UtilsCleanup
Utils cleanup
2015-10-09 06:59:33 -04:00
Anthony Whitford
960283bdcf Do not need or want to call toString for a logger parameter. 2015-10-09 02:08:07 -07:00
Anthony Whitford
39f30eab7a Re-use Document and Field instances to minimize GC overhead. See http://wiki.apache.org/lucene-java/ImproveIndexingSpeed 2015-10-09 00:38:55 -07:00
Anthony Whitford
24b4741aaf Removed unnecessary @SuppressWarnings. 2015-10-08 23:40:14 -07:00
Anthony Whitford
64f373fb43 Removed old warning suppression. 2015-10-08 20:58:20 -07:00
Anthony Whitford
bc1830d8eb Removed redundant call to length for substring. 2015-10-08 20:57:28 -07:00
Anthony Whitford
f2a2a91682 Slight simplification to standard getInt and getLong. 2015-10-08 00:56:38 -07:00
Anthony Whitford
274ac339ad Corrected a few bugs in Settings. 2015-10-08 00:39:57 -07:00
Anthony Whitford
1d916286ee Changing the check phase from compile to verify. 2015-10-07 23:11:53 -07:00
Jeremy Long
832d54300a fixed suppression for issue #365 2015-10-03 07:41:15 -04:00
Jeremy Long
ba6d3bbe15 added suppression for issue #365 2015-10-03 07:35:05 -04:00
Jeremy Long
c1d0789ac7 the Central analyzer should be enabled by default 2015-09-30 06:37:47 -04:00
Dale Visser
0573d0083e Ruby Bundler: Throw AnalysisException in initialize if can't run bundle-audit. 2015-09-22 15:07:43 -04:00
Dale Visser
e57d62b682 Merge branch 'upmaster' into ruby-bundler
Conflicts:
	dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
	dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
	dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
2015-09-22 14:21:43 -04:00
Jeremy Long
bb6f27b322 updated other tool(s) listed 2015-09-22 06:12:10 -04:00
Jeremy Long
86f424ad37 Merge pull request #358 from wmaintw/master
update the version of dependency-check-core that the gradle plugin used
2015-09-22 06:01:19 -04:00
ma wei
ad81bbc761 modify README 2015-09-21 09:26:25 +08:00
ma wei
07e868e6f6 upgrade dependency check core version to 1.3.1 2015-09-21 09:24:58 +08:00
Jeremy Long
b45700df03 version 1.3.1 2015-09-20 07:17:00 -04:00
Jeremy Long
93ce2a8e3a fixed path in zip to be different then the cli 2015-09-20 07:14:02 -04:00
Jeremy Long
fbc4d46962 updated language list to include php 2015-09-20 06:39:55 -04:00
Jeremy Long
d73d138b3f checkstyle/pmd/findbugs corrections 2015-09-20 06:39:27 -04:00
Jeremy Long
14ea21d53d checkstyle/pmd/findbugs corrections 2015-09-20 06:38:47 -04:00
Jeremy Long
2b3791b83e checkstyle/findbugs/pmd/copyright corrections 2015-09-19 08:20:58 -04:00
Jeremy Long
e04809f96b checkstyle/findbugs/pmd/copyright corrections 2015-09-19 08:20:14 -04:00
Jeremy Long
9203acff9c checkstyle/pmd/findbugs patches 2015-09-19 07:52:24 -04:00
Jeremy Long
afc1a9f077 removed unused settings 2015-09-18 06:53:30 -04:00
Jeremy Long
fc57851113 added options to disable analyzers 2015-09-18 06:52:36 -04:00
Jeremy Long
1f1d3f843f Merge branch 'colezlaw-composer-json' 2015-09-18 05:47:35 -04:00
Jeremy Long
b389260dec updated copyright 2015-09-18 05:47:06 -04:00
ma wei
1f37a5ff8f update the example command in README file 2015-09-17 17:17:41 +08:00
ma wei
815d60eca2 update README, fix typo which would lead to unable to apply this plugin 2015-09-17 17:15:42 +08:00
Dale Visser
877a584a26 Ruby Bundler: Disable Gemspec analysis if successful init. Moved to new analysis phase after init, before info collection. 2015-09-15 12:27:26 -04:00
Dale Visser
0c60c9ff75 Merge branch 'upmaster' into ruby-bundler 2015-09-15 11:59:59 -04:00
Will Stranathan
6a7a868b71 Initial checkin of ComposerLockAnalyzer 2015-09-14 22:14:00 -04:00
Jeremy Long
b5a070b228 Merge pull request #345 from hansjoachim/upgrades
Upgrade jmockit to 1.19
2015-09-14 19:29:15 -04:00
Dale Visser
39f13c6e5b Merge branch 'upmaster' into ruby-bundler 2015-09-14 17:14:20 -04:00
Jeremy Long
8c98da09f0 Merge pull request #355 from hansjoachim/warnings
Warnings
2015-09-13 19:31:16 -04:00
Jeremy Long
ed70a7200c Merge pull request #356 from awhitford/CompilerWarn
Enabled Compiler Lint Check and Deprecation Warnings
2015-09-13 19:28:26 -04:00
Anthony Whitford
ea4410cd16 Added missing serialVersionUID. 2015-09-13 10:57:54 -07:00
Anthony Whitford
9d9b1cbcd5 Replaced hashCode to leverage builder instead of deprecated ObjectUtils methods. 2015-09-13 10:55:02 -07:00
Anthony Whitford
f17d8f38fb Replaced equals and hashCode to leverage builders instead of deprecated ObjectUtils methods. 2015-09-13 10:48:03 -07:00
Anthony Whitford
0efc9d1cd2 Added missing serialVersionUID. 2015-09-13 10:34:19 -07:00
Anthony Whitford
4f5d5f1afd Added missing serialVersionUID. 2015-09-13 10:30:08 -07:00
Anthony Whitford
c4d8d7abf4 Removed redundant maven-compiler-plugin declaration. 2015-09-13 10:22:44 -07:00
Anthony Whitford
3fad29a709 Enabled lint check and deprecation warnings during compilation. 2015-09-13 10:22:25 -07:00
Hans Joachim Desserud
665f204c1f Code review: remove outcommented @Override annotation 2015-09-13 19:05:53 +02:00
Hans Joachim Desserud
362b651823 Unused imports 2015-09-13 17:06:44 +02:00
Hans Joachim Desserud
49b56588b8 Replace with foreach 2015-09-13 17:04:46 +02:00
Hans Joachim Desserud
c7a763ffdc Remove inheritance from Junit3 class and empty, unused methods 2015-09-13 17:01:32 +02:00
Hans Joachim Desserud
5435ddad9f Place array designator on the type 2015-09-13 16:46:14 +02:00
Hans Joachim Desserud
0ecd466c4c Add missing @Override annotations 2015-09-13 14:52:08 +02:00
Jeremy Long
6117e25b97 resolved merge 2015-09-13 07:49:25 -04:00
Jeremy Long
ee10f09bc6 Merge branch 'awhitford-StringB' 2015-09-13 07:47:11 -04:00
Jeremy Long
58512e302f resolved conflicts 2015-09-13 07:46:46 -04:00
Jeremy Long
ce564c209b removed deprecated/unused methods 2015-09-13 07:43:05 -04:00
Jeremy Long
7296d49693 Merge pull request #352 from awhitford/mpirp
Upgraded maven-project-info-reports-plugin from 2.8 to 2.8.1.
2015-09-13 07:41:01 -04:00
Jeremy Long
290fdc4c0f Merge pull request #350 from awhitford/AnalyzeIO
Replaced code with IOUtils.copy.

Thanks for the PR!
2015-09-13 07:40:41 -04:00
Jeremy Long
1fa5ae695d Merge pull request #349 from hansjoachim/warnings
Fixes various warnings
2015-09-13 07:37:25 -04:00
Jeremy Long
b2ba6d38b8 Merge branch 'hansjoachim-directoryscanner' 2015-09-13 07:29:56 -04:00
Jeremy Long
620f1b94bc added more false positive suppressions 2015-09-13 07:29:17 -04:00
Jeremy Long
c8fb5d1a9a excluded ant-launcher 2015-09-13 07:28:41 -04:00
Jeremy Long
1f763aeb72 Merge branch 'directoryscanner' of https://github.com/hansjoachim/DependencyCheck into hansjoachim-directoryscanner 2015-09-13 07:13:47 -04:00
Jeremy Long
fcfb019555 suppressed findbugs redundant null check 2015-09-13 07:03:55 -04:00
Jeremy Long
d4c1acb126 checkstyle fix - empty catch 2015-09-13 07:03:15 -04:00
Jeremy Long
862bf43685 suppressed checkstyle warnings 2015-09-13 07:02:41 -04:00
Jeremy Long
f83139a9ee fixed line length checkstyle finding 2015-09-13 07:02:13 -04:00
Jeremy Long
3d938b3edf added findbugs annotations to allow suppression 2015-09-13 07:01:28 -04:00
Jeremy Long
6c6ae66e36 added SuppressionCommentFilter so we can suppress individual findings 2015-09-13 07:01:10 -04:00
Jeremy Long
813e423bec added findbugs annotations to allow suppression 2015-09-13 07:00:27 -04:00
Anthony Whitford
a9a235fc87 Replaced StringBuffer with more efficient StringBuilder. 2015-09-12 19:53:44 -07:00
Anthony Whitford
6e1c6b4bed Replaced StringBuffer with more efficient StringBuilder. 2015-09-12 19:50:43 -07:00
Anthony Whitford
2214059a63 Upgraded maven-project-info-reports-plugin from 2.8 to 2.8.1. Also enabled cim report (since ci is being used). 2015-09-12 18:48:30 -07:00
Anthony Whitford
424cfcfa0c Added optional merge property support via a database dialect. Note that saveProperties was broken and unused, so removed. 2015-09-12 14:13:46 -07:00
Anthony Whitford
ce871dfa3e Replaced code with IOUtils.copy. 2015-09-12 10:55:33 -07:00
Hans Joachim Desserud
48a6eb1f86 Prefer interfaces over concerete classes. Did not change return type for public methods as this might potentially cause problems/need for changes for external users 2015-09-12 15:35:56 +02:00
Hans Joachim Desserud
fb85fb5b76 Ensure that we assert something. If the iterator doesn't have any values we would never enter the loop, but the test would still be green 2015-09-12 15:03:41 +02:00
Hans Joachim Desserud
c39c3cfdae Comment for review 2015-09-12 15:02:22 +02:00
Hans Joachim Desserud
e2fa7c666a Unused variable 2015-09-12 14:53:01 +02:00
Hans Joachim Desserud
f49cc6fb1f Unused methods in test 2015-09-12 14:51:49 +02:00
Hans Joachim Desserud
69bef59473 Remove superflous semicolon 2015-09-12 14:50:35 +02:00
Hans Joachim Desserud
9e931b9eb0 Remove modified copy of Apache Ant's DirectoryScanner 2015-09-12 14:14:54 +02:00
Hans Joachim Desserud
b26d9ea1e0 Replace use of included DirectoryScanner with Apache Ant's 2015-09-12 14:14:53 +02:00
Hans Joachim Desserud
ca5607d79e Removed empty methods from test 2015-09-12 14:14:08 +02:00
Hans Joachim Desserud
903eaed250 Remove unused imports 2015-09-12 14:06:47 +02:00
Jeremy Long
0859eab2dc corrected documentation 2015-09-12 06:59:19 -04:00
Jeremy Long
f0f84722ba removed unused import 2015-09-12 06:59:07 -04:00
Hans Joachim Desserud
17b8ba7069 Upgrade jmockit to 1.19 2015-09-12 12:40:01 +02:00
Jeremy Long
eb91152cfa updated the dependency-check-ant documentation 2015-09-11 06:53:58 -04:00
Jeremy Long
08c1b6879e changed scope on ant dependencies to provided 2015-09-11 06:15:59 -04:00
Jeremy Long
0077a8f67c removed link to usage.html as it was removed 2015-09-11 06:15:26 -04:00
Jeremy Long
a89cc67bd2 fixed hyperlink (usage->index) 2015-09-11 06:14:47 -04:00
Jeremy Long
388415ecc2 fixed hyperlink 2015-09-11 06:13:30 -04:00
Jeremy Long
44c5ba208d added documentation about unused code 2015-09-11 05:31:09 -04:00
Jeremy Long
d3a51857cb Merge pull request #344 from awhitford/DbOpts
Db opts
2015-09-11 05:25:16 -04:00
Anthony Whitford
11a3db5d64 Revert "Replaced update or insert property logic with merge property logic."
This reverts commit ece4a51b94.
2015-09-10 23:21:44 -07:00
Anthony Whitford
f3be8ae608 Merge remote-tracking branch 'jeremylong/master' into DbOpts 2015-09-10 23:17:46 -07:00
Jeremy Long
0577c9121c merge conflicts resolved 2015-09-10 06:47:38 -04:00
Jeremy Long
058f51e8c1 removed the shade plugin 2015-09-10 06:43:43 -04:00
Jeremy Long
698444caec changed the name of the data directory 2015-09-10 06:42:48 -04:00
Jeremy Long
d575df4b19 updated release to correctly bundle the zip 2015-09-10 06:42:25 -04:00
Jeremy Long
bee98513a2 cleaned up notices because additional notices are no longer added by shade 2015-09-10 06:41:48 -04:00
Anthony Whitford
3746df49ee Added type declarations. 2015-09-10 00:21:54 -07:00
Anthony Whitford
d98f67eab9 Added missing serialVersionUID. 2015-09-10 00:20:03 -07:00
Anthony Whitford
fde415e251 Added missing serialVersionUID. 2015-09-10 00:05:04 -07:00
Anthony Whitford
5702f39181 Addressed possible resource leak. 2015-09-09 23:54:20 -07:00
Anthony Whitford
45658afd89 Replaced empty string equals check with an isEmpty check. 2015-09-09 23:20:51 -07:00
Anthony Whitford
ece4a51b94 Replaced update or insert property logic with merge property logic. 2015-09-09 23:18:38 -07:00
Dale Visser
837d4918f2 Merge branch 'upmaster' into ruby-bundler. Fixed omission of --disableBundleAudit option.
Conflicts:
	dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
2015-09-09 18:09:41 -04:00
Jeremy Long
57ae0f1676 resolved command line invocation of aggregate resulting in missing html report (#189) 2015-09-09 06:15:17 -04:00
Jeremy Long
48e644e007 removed un-needed call to log.isDebugEnabled() 2015-09-09 05:58:51 -04:00
Jeremy Long
49a04fa913 Merge branch 'awhitford-FluidoSkin14' 2015-09-08 06:43:06 -04:00
Jeremy Long
df943bcf75 Merge branch 'FluidoSkin14' of https://github.com/awhitford/DependencyCheck into awhitford-FluidoSkin14 2015-09-08 06:35:14 -04:00
Jeremy Long
fdbec176fa fixed logging statements to use slf4j format syntax instead of String.format syntax 2015-09-08 06:31:59 -04:00
Jeremy Long
4b2b4e5482 Merge pull request #343 from awhitford/CodeTweaks
Code tweaks
2015-09-08 06:20:18 -04:00
Anthony Whitford
96768d8529 Replaced Date manipulation with more efficient System call. 2015-09-08 01:01:13 -07:00
Anthony Whitford
2689a08026 Replaced Date manipulation with more efficient System call. 2015-09-07 17:50:02 -07:00
Anthony Whitford
54be70672e Replaced Date manipulation with more efficient System call. 2015-09-07 17:49:11 -07:00
Anthony Whitford
480fa50af5 Corrected Javadoc to eliminate warning. 2015-09-07 17:01:24 -07:00
Anthony Whitford
b51731d15f Added final keyword. 2015-09-07 16:35:23 -07:00
Anthony Whitford
c09650a136 Removed unused slf4j-ext and slf4j-jdk14 dependency declarations. 2015-09-07 16:30:58 -07:00
Anthony Whitford
769fcb20d8 Removed a now unused import. 2015-09-07 16:29:27 -07:00
Anthony Whitford
537c4b3a50 Added missing final keywords. 2015-09-07 16:28:55 -07:00
Anthony Whitford
a75c17ac5e Added final keywords and elaborated the javax.json imports. 2015-09-07 16:28:22 -07:00
Anthony Whitford
85604e8afa Logback-core is a transitive dependency from logback-classic -- no need to explicitly mention it. JSoup type is jar by default, so no need to mention that. SLF4J-Ext does not seem to be used, so can drop that. H2 only has runtime scope. 2015-09-07 16:01:10 -07:00
Anthony Whitford
9a45c9aa7c Removed unused Cal10n MessageConveyor. 2015-09-07 15:21:54 -07:00
Anthony Whitford
01450bacc2 Removed a redundant null check, and replaced an addAll with the constructor population. 2015-09-07 14:51:26 -07:00
Anthony Whitford
af0255ee09 Rather than create a collection, then call addAll to populate, the collection can be created with the collection to clone. 2015-09-07 14:48:23 -07:00
Anthony Whitford
df25bbb6d2 Replaced json iteration with more efficient entrySet. Also corrected an invalid logging statement. 2015-09-07 14:43:34 -07:00
Anthony Whitford
444685bc05 Inner class should be static (since it doesn't reference parent). 2015-09-07 14:40:32 -07:00
Anthony Whitford
115f63c330 Removed an unused import and combined nested if statements. 2015-09-07 14:38:43 -07:00
Anthony Whitford
f9dbc4f7bf Upgraded Fluido Skin to 1.4 (from 1.3.1). 2015-09-07 10:54:01 -07:00
Jeremy Long
83263f8dee Update README.md
added build badge
2015-09-07 07:43:33 -04:00
Jeremy Long
a452ade957 Merge pull request #339 from awhitford/DependencyUpgrades
Upgraded dependencies.
2015-09-07 07:36:47 -04:00
Jeremy Long
1f48af024e Merge pull request #338 from awhitford/PomCleanup
Pom cleanup
2015-09-07 07:34:07 -04:00
Jeremy Long
0a643d7195 Merge pull request #340 from awhitford/CommonsLang3
Upgraded commons-lang-2.6 to newer commons-lang3-3.4.
2015-09-07 07:30:52 -04:00
Jeremy Long
c3835b9da7 removed erroneous short cli argument for exclude 2015-09-07 07:27:39 -04:00
Jeremy Long
bb1a96cf7a Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-09-07 07:25:36 -04:00
Jeremy Long
56360301d7 changed debug message to an error 2015-09-07 07:25:29 -04:00
Jeremy Long
435cccdeae Merge pull request #341 from awhitford/CommonsCli131
Upgraded commons-cli to 1.3.1 (from 1.2).
2015-09-07 07:24:48 -04:00
Anthony Whitford
b11b472933 Upgraded commons-cli to 1.3.1 (from 1.2). See http://commons.apache.org/proper/commons-cli/release_1_3.html for upgrade details. 2015-09-07 02:27:10 -07:00
Anthony Whitford
514f8398e2 Upgraded commons-lang-2.6 to newer commons-lang3-3.4. 2015-09-07 01:09:41 -07:00
Anthony Whitford
90935fef25 Upgraded dependencies. 2015-09-07 00:40:30 -07:00
Anthony Whitford
9b5ce1c3a6 Upgraded shade plugin to 2.4.1 (from 2.3). 2015-09-06 23:20:15 -07:00
Anthony Whitford
8ad1639b02 License is inherited from Parent POM -- no need to restate unless it is different. 2015-09-06 22:30:01 -07:00
Anthony Whitford
6d70332cd6 Centralized the Versions report to the parent pom. 2015-09-06 22:21:50 -07:00
Anthony Whitford
717f6240e3 Centralized javadoc reporting to parent pom. 2015-09-06 20:51:56 -07:00
Anthony Whitford
ab782054a1 Missed this lingering redundant maven-project-info-reports-plugin declaration. 2015-09-06 13:37:04 -07:00
Anthony Whitford
b481f01217 Moved the maven-plugin-plugin declarations into the maven module since it is unique to that module. 2015-09-06 13:05:17 -07:00
Anthony Whitford
d0f884f5b2 Centralized the maven-surefire-report-plugin to the parent pom. Note that gradle and jenkins modules are skipped since it does not apply. 2015-09-06 12:56:36 -07:00
Anthony Whitford
51e66354b0 No need to explicitly add a jar goal when it implicitly exists already for a jar module. 2015-09-06 11:18:56 -07:00
Jeremy Long
1efe90f445 Merge pull request #337 from awhitford/Checkstyle
Thanks again!
2015-09-06 06:12:19 -04:00
Anthony Whitford
7b47b7549d Removed redundant declarations for maven-compiler-plugin and maven-jar-plugin. 2015-09-06 01:42:01 -07:00
Anthony Whitford
7ccb77fb57 Removed unnecessary property for findbugs-maven-plugin since it is now only declared once. 2015-09-06 01:32:00 -07:00
Anthony Whitford
a32fa69823 Moved taglist-maven-plugin to the parent pom. (Gradle and Jenkins modules don't have them -- before or after.) This will make it easier to manage and evolve. 2015-09-06 01:29:17 -07:00
Anthony Whitford
ece4cb03ad project.build.sourceEncoding is already specified in the parent pom, so this is not necessary. 2015-09-06 00:53:53 -07:00
Anthony Whitford
5c53b6528f Centralized the findbugs-maven-plugin to the parent pom. Gradle and Jenkins modules skip it naturally. The onlyAnlyze setting for utils is maintained via a property. Also was able to upgrade to latest plugin, version 3.0.2. 2015-09-06 00:51:28 -07:00
Anthony Whitford
9b92007eff Centralized cobertura plugin to the parent pom and was able to upgrade it from 2.6 to 2.7. 2015-09-06 00:23:24 -07:00
Anthony Whitford
e433809f4d Moved maven-jxr-plugin and maven-project-info-reports-plugin reporting declarations into the parent pom. No need to duplicate in child modules. Utils did not have project-info reports, but there does not seem to be a good reason. Also note that the JXR plugin is naturally skipped when it does not apply (there is no java code), so not necessary to explicitly skip it for gradle and jenkins modules. 2015-09-05 23:57:53 -07:00
Anthony Whitford
d74218004a Reporting section for jenkins module is completely redundant with the parent pom. It can be removed and will generate the same report. 2015-09-05 23:17:28 -07:00
Anthony Whitford
c35276e3df Reporting section for gradle module is completely redundant with the parent pom. It can be removed and will generate the same report. 2015-09-05 23:15:35 -07:00
Anthony Whitford
064236ed5b Added Dependency plugin to Reporting section because it has an excellent Dependency Analysis Report. 2015-09-05 22:56:36 -07:00
Anthony Whitford
2a50dcba9d Removed Checkstyle and PMD violations. 2015-09-05 22:25:59 -07:00
Anthony Whitford
f7974b324b Exclude generated HelpMojo.java file from Checkstyle analysis. 2015-09-05 22:25:38 -07:00
Jeremy Long
3bb716b060 Merge pull request #336 from awhitford/Timing
Added time measurements for key steps.
2015-09-05 21:08:05 -04:00
Jeremy Long
39e465261f Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-09-05 21:07:47 -04:00
Jeremy Long
784b78b17c added another timer to pull #336 2015-09-05 21:07:29 -04:00
Jeremy Long
22c68ed8ef Merge pull request #331 from wmaintw/master
add compatibility supports
2015-09-05 21:00:15 -04:00
Jeremy Long
c4c670a3b1 Merge pull request #334 from awhitford/MavenPluginWarnings
Removed deprecated code.
2015-09-05 20:59:05 -04:00
Jeremy Long
17a05cc1d4 removed excessive logging used to debug 2015-09-05 20:56:54 -04:00
Jeremy Long
d452c5fabb fixed shift operator per issue #335 2015-09-05 20:56:18 -04:00
Jeremy Long
2cf974ef02 maven-reporting-api cannot be scoped to provided 2015-09-05 07:09:01 -04:00
Jeremy Long
1f0e789575 fixed bug that might contribute to issue #189 2015-09-05 06:48:00 -04:00
Anthony Whitford
92e1fd3f28 Added time measurements for key steps. 2015-09-05 00:31:50 -07:00
Jeremy Long
49736a87aa Merge branch 'awhitford-FixSite' 2015-09-03 05:32:06 -04:00
Anthony Whitford
d009e39842 Removed unnecessary maven-site-plugin dependency, and maven-plugin-annotations dependency is provided. 2015-09-03 01:47:46 -07:00
Anthony Whitford
c2b8901537 Removed deprecated code. 2015-09-03 01:25:53 -07:00
Anthony Whitford
dd910cb5ec Updated plugins. 2015-09-03 00:48:06 -07:00
Jeremy Long
4632753f02 commented out initial attempt at issue #22 to resolve issue #327 2015-09-02 06:42:36 -04:00
Jeremy Long
3fdcd12b4f maven dependencies should be marked as provided per issue #329 2015-09-02 06:05:56 -04:00
ma wei
94d1d611c7 add compatibility supports 2015-09-02 13:45:06 +08:00
Jeremy Long
27b54a0bfa changed taskdef.properties file name 2015-09-01 06:37:44 -04:00
Jeremy Long
1b1ecd0748 split monolithic taskdef into three primary taskdefs 2015-08-31 06:59:57 -04:00
Dale Visser
1e29d2e751 Merge branch 'upmaster' into ruby-bundler
Conflicts:
	dependency-check-cli/src/main/java/org/owasp/dependencycheck/CliParser.java
2015-08-30 15:11:33 -04:00
Dale Visser
a0437bf933 Ruby bunder: Code needed to disable the analyzer in the CLI if desired. 2015-08-30 15:07:21 -04:00
Dale Visser
73e0292a4b Ruby Bundler: Added informative message about updating DB. Switched most log messages to debug level. 2015-08-30 14:52:55 -04:00
Dale Visser
c393e74160 Ruby bundler: Better message and logging when bundle-audit not found. 2015-08-30 14:31:58 -04:00
Dale Visser
80c4666198 Ruby bundler: More method extractions to eliminate monolithic method. 2015-08-30 14:16:32 -04:00
Dale Visser
ea7bd1f700 Ruby bundler: tidied up how extracted method is used. 2015-08-30 14:06:47 -04:00
Dale Visser
b3a55cc85d Ruby bundler: extracted method 2015-08-30 13:57:30 -04:00
Dale Visser
036200350d Ruby bundler: add needed null checks to avoid NPEs. 2015-08-30 13:50:22 -04:00
Jeremy Long
e630c484ff implementing the purge feature as requested in issue #328 2015-08-30 07:02:26 -04:00
Dale Visser
713e9658c5 Ruby bundler: got description working. Added boilerplate text describing differences from standard D-C vulnerability report. 2015-08-29 12:29:44 -04:00
Dale Visser
782039810e Ruby Bundler: Added URL to report. 2015-08-29 11:33:16 -04:00
Dale Visser
b473d8ab9c Ruby Bundler: Added URL to report. 2015-08-29 11:28:38 -04:00
Dale Visser
2eb6918fb3 Ruby Bundler: Clean up report a little bit, and grouped vulnerabilities under dependencies, when appropriate. 2015-08-29 11:06:24 -04:00
Jeremy Long
29626666a7 removed debug logging 2015-08-29 08:38:49 -04:00
Jeremy Long
dc41c9a671 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-08-29 08:02:42 -04:00
Jeremy Long
83af70bb59 corrected argument name for the purge nvd option 2015-08-29 07:57:54 -04:00
Jeremy Long
b293873640 finished deprecating the application name argument in favor of project name per issue #320 2015-08-29 07:12:40 -04:00
Jeremy Long
8bb92815cb added argument to purge local NVD per issue #328 2015-08-29 06:58:13 -04:00
Jeremy Long
7a8f7199c8 renaming app argument to project per issue #320 2015-08-29 06:48:52 -04:00
Dale Visser
6f4ce34840 Ruby Bundler: Added CVSS score and a little hack to avoid dependency bundling. 2015-08-28 21:31:01 -04:00
Dale Visser
8853552161 Ruby Bundler: Successfully adding vulnerability into report, though all displayed info not looking great. 2015-08-28 19:56:35 -04:00
Dale Visser
95d3d17d83 Ruby Bundler: Now successfully creating temp files for dependency objects. 2015-08-28 13:58:49 -04:00
Jeremy Long
3594280b04 Merge pull request #326 from dwvisser/doc-updates
Added previously overlooked documentation for CMake, Node.js and Ruby Gems Analyzers
2015-08-28 06:12:54 -04:00
Jeremy Long
1e447c6e3e Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-08-28 05:27:16 -04:00
Jeremy Long
c41a288280 added null checks 2015-08-28 05:27:00 -04:00
Dale Visser
a0492fe944 Merge branch 'upmaster' into ruby-bundler
Conflicts:
	dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
2015-08-27 14:05:36 -04:00
Dale Visser
1fffebd497 Docs: Added Ruby Gemspec analyzer page, fixed typos on Node.js page. 2015-08-26 14:40:36 -04:00
Dale Visser
62c05049a7 Docs: Added node.js page, fixed typos in Python page. 2015-08-26 14:25:32 -04:00
Dale Visser
0fdf377d45 Docs: Added CMake analyzer page. 2015-08-26 14:11:30 -04:00
Dale Visser
6ca8e2644a Docs: Fixed sidebar links to OpenSSL and Python analyzer pages. 2015-08-26 13:59:28 -04:00
Dale Visser
4a3061db6d Docs: Added CMake to landing page, and links to Autoconf and CMake. Added missing analyzers to analyzers list. Shortened my analyzer URLs, though not all in site index yet. 2015-08-26 13:54:15 -04:00
Dale Visser
61ac81518a Docs: Added Ruby and Node.js to landing page. Added table row for Node.js in Analyzers list. 2015-08-26 12:27:38 -04:00
Jeremy Long
acd4b4371d Merge pull request #323 from wmaintw/master
Implement the nested configuration for proxy and cve related settings
2015-08-26 06:05:38 -04:00
Jeremy Long
1d20291d44 Merge branch 'dwvisser-node-js-analyzer' 2015-08-26 06:03:32 -04:00
Dale Visser
c60245ea2b Node.js Analyzer: Switched from org.json to Glassfish JSR 353 reference implementation. 2015-08-25 17:28:17 -04:00
Dale Visser
9e25480baa Merge branch 'upmaster' into node-js-analyzer
Conflicts:
	dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java
	dependency-check-cli/src/site/markdown/arguments.md
	dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer
2015-08-25 13:03:12 -04:00
ma wei
facd803943 update README file 2015-08-25 23:17:12 +08:00
ma wei
05c8a6282d upgrade to 0.0.7 2015-08-25 23:06:34 +08:00
ma wei
3f9ae34203 refactor: change method name for override settings 2015-08-25 19:50:50 +08:00
ma wei
afb85309a2 implement nested configuration for CVE settings 2015-08-25 19:49:03 +08:00
ma wei
2c5e64d0d5 update README for configuration change 2015-08-25 19:17:55 +08:00
ma wei
ddb8c432be implement the nested configuration for proxy settings 2015-08-25 19:11:27 +08:00
Jeremy Long
054be314f6 added targetCompatibility = 1.7 per issue #321 2015-08-25 06:13:29 -04:00
Jeremy Long
e484c5754e Merge pull request #312 from dwvisser/rubygems-analyzer-pr
Rubygems analyzer
2015-08-25 05:31:10 -04:00
Jeremy Long
b36c4f65e5 Merge pull request #322 from wmaintw/master
Remove duplicated configuration items in DependencyCheckTask
2015-08-25 05:28:34 -04:00
Jeremy Long
4bdfbcc916 Merge pull request #316 from dwvisser/iso-scanning
Help for scanning ISO images on Linux, Mac OS X, and Windows
2015-08-25 05:27:10 -04:00
ma wei
519198bb61 Merge remote-tracking branch 'upstream/master' 2015-08-24 22:29:28 +08:00
ma wei
9a7c342f91 modify spec for testing project extension 2015-08-24 22:25:03 +08:00
ma wei
761a5ed3dd remove duplicated configuration items in DependencyCheckTask 2015-08-24 22:17:16 +08:00
Jeremy Long
481e753ad4 corrected spring-security false positives per issue #319 and #311 2015-08-23 06:45:35 -04:00
Dale Visser
271016f0fa Added verbose flag to get as much reportable info as possible. 2015-08-19 15:33:50 -04:00
Dale Visser
4493f895c6 Added test resources to cover interesting bundle-audit cases. 2015-08-19 15:26:17 -04:00
Dale Visser
5c32ecd8e1 Ruby Analyzer: Added bundle-audit analyzer. So far just launches if available and logs the output. 2015-08-18 16:59:39 -04:00
Dale Visser
0b5244d321 Markdown escape * character fix 2015-08-18 12:37:09 -04:00
Jeremy Long
b6f9715174 Merge pull request #318 from dwvisser/code-inspection-fixes
Random fixes to issues found by IntelliJ IDEA code inspection.
2015-08-17 19:46:41 -04:00
Dale Visser
2db1f8d2b6 Random fixes to issues found by IntelliJ IDEA code inspection. 2015-08-17 18:55:51 -04:00
Dale Visser
4c5957ae40 ISO scanning: Fixed slight errors in Python file types, and made formatting consistent. 2015-08-17 14:49:24 -04:00
Dale Visser
38cd19de15 ISO scanning: Added clarification on what can be scanned. Fleshed out file type analyzers page with details. Re-ordered side menu alphabetically to match. 2015-08-17 12:16:45 -04:00
Jeremy Long
f66ffbdd63 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-08-16 06:25:02 -04:00
Jeremy Long
8d3f08e529 fixed links 2015-08-16 06:24:08 -04:00
Jeremy Long
4209c1c406 Merge pull request #315 from recena/master
Fixed links
2015-08-16 06:17:24 -04:00
Dale Visser
1cd12d0a0c Documentation giving help for scanning ISO images on Linux, Mac OS X, and Windows. 2015-08-14 13:51:38 -04:00
Manuel Recena
7eb18e1931 Fixed links 2015-08-14 12:33:47 +02:00
ma wei
d308e50e1e remove duplicated plugin properties file 2015-08-14 17:12:28 +08:00
Dale Visser
88569cb369 rubygems: Finished command-line interface integration. 2015-08-12 12:08:05 -04:00
Dale Visser
235869fc79 rubygems: Reformat and consisitent parameter naming in private methods. 2015-08-12 12:08:05 -04:00
Dale Visser
89166e81fb rubygems: Add summary to evidence, inline constants that were only being used once. 2015-08-12 12:08:05 -04:00
Dale Visser
2d109b81cf rubygems: Used substring(int) to remove the need for Matcher.find(int).
Also fixed javadoc, made some variables final, shortened a variable name.
2015-08-12 12:06:18 -04:00
Dale Visser
5c02b4dccb rubygems: Added new analyzer to META-INF/services. Confirmed correlation with CPE in CLI. 2015-08-12 12:06:18 -04:00
Dale Visser
e7f154b58d rubygems: Various refactoring improvements. 2015-08-12 12:00:56 -04:00
Dale Visser
c0752575c6 rubygems: All evidence assertions now passing. 2015-08-12 12:00:43 -04:00
Dale Visser
7eb2c89f39 rugygems: Added gemspec test resources, test cases, and minimal code to run tests and have evidence gathering test fail. 2015-08-12 11:58:46 -04:00
Dale Visser
bf4eb07342 Node.js: Added missing command-line option for disableing Node.js analyzer. 2015-08-11 15:27:20 -04:00
Jeremy Long
c856d01b52 removed un-needed dependencies 2015-08-09 16:05:14 -04:00
Dale Visser
7a535b2576 node.js: Added parent folder to display file name. Added try-catch for JSONException, logging warning message in that case. 2015-08-09 11:32:57 -04:00
Dale Visser
4b17fd88a3 node.js: Adding name_project to vendor evidence, as many node.js projects seem to follow this pattern with their CPEs. Also, logging warnings whenever JSON parse doesn't go as expected. 2015-08-09 11:18:16 -04:00
Jeremy Long
8d1f3f723f version 1.3.1-SNAPSHOT 2015-08-09 10:25:44 -04:00
Jeremy Long
a543fbbec9 added an additional attempt to remove the temporary directory 2015-08-09 10:25:30 -04:00
Jeremy Long
37f50db00e removed related dependencies from hashCode and equals to resolve issue #293 2015-08-09 09:56:20 -04:00
Jeremy Long
ccb87f43b7 made suppression notes textarea readonly to resolve issue #306 2015-08-09 09:36:55 -04:00
Jeremy Long
d569f39f53 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2015-08-09 09:10:32 -04:00
Jeremy Long
fb3951772f fixed errors due to null values per issue #309 2015-08-09 09:10:18 -04:00
Jeremy Long
2c00bf4040 Merge pull request #305 from wmaintw/master
[new pull request] Implement configuration item "quickQueryTimpstamp" in grade plugin
2015-08-07 18:26:03 -04:00
Dale Visser
4f8772bd77 node.js: Added parameter to cli. 2015-08-07 16:10:56 -04:00
Dale Visser
b4c3046ab5 node.js: Added package.json eveidence gathering, using json.org package for the parsing. 2015-08-07 15:41:01 -04:00
Dale Visser
2441b92bc6 node.js: Initial commit, with analysis test failing. 2015-08-07 14:43:08 -04:00
ma wei
c39eec32f2 ignore gradle generated temporary files 2015-08-07 10:14:34 +08:00
ma wei
7837718d04 update README file 2015-08-07 10:13:53 +08:00
ma wei
7069671471 fix issue that fail to publish gradle plugin to gradle plugin portal 2015-08-07 10:13:27 +08:00
ma wei
d1dbde2890 fix issue that fail to publish gradle plugin to maven central 2015-08-07 10:13:00 +08:00
ma wei
0472471ac9 update the gradle plugin version to 0.0.6 2015-08-07 10:11:34 +08:00
ma wei
62a0b8da90 add configuration, let user has ability to control HTTP method used during the update process to avoid proxy problem 2015-08-07 10:09:40 +08:00
ma wei
810530fabd upgrade dependency check core and utils version to 1.3.0 2015-08-07 10:08:37 +08:00
Jeremy Long
707de56612 Merge pull request #302 from dwvisser/290-add-bz2-format
Add bzip2 format to ArchiveAnalyzer
2015-08-06 07:02:21 -04:00
Jeremy Long
921b0eb229 Merge pull request #301 from dwvisser/run-against-cached-db-pr
Help page for how to use multiple local snapshots of the NVD
2015-08-05 22:54:33 -04:00
Jeremy Long
9afb92f0ed Merge pull request #303 from colezlaw/homebrew-cli-instructions
Added homebrew installation instructions
2015-08-05 22:52:36 -04:00
Will Stranathan
1ded88e089 Added homebrew installation instructions 2015-08-05 20:58:20 -04:00
Dale Visser
1f074ff400 290: Further refactoring for readability. 2015-08-05 17:42:25 -04:00
Dale Visser
4764f61b48 290: Added unit tests and implementation to support bzip2. 2015-08-05 17:42:10 -04:00
Dale Visser
56424924bb 290: Extracted some methods to reduce average method size, and eliminate some duplicate code. 2015-08-05 17:42:10 -04:00
Dale Visser
4c3831ec74 Removed superfluous phrase. 2015-08-05 12:03:21 -04:00
Dale Visser
ba564a6aed Added page to site that documents how to take daily snapshots of the NVD,
and run D-C cli against those snapshots.
2015-08-05 11:57:23 -04:00
571 changed files with 64389 additions and 31179 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
*.html linguist-documentation
(^|/)site/) linguist-documentation

34
.github/contributing.md vendored Normal file
View File

@@ -0,0 +1,34 @@
# Contributing to OWASP dependency-check
## Reporting Bugs
- Ensure you're running the latest version of dependency-check.
- Ensure the bug has not [already been reported](https://github.com/jeremylong/DependencyCheck/issues).
- If you're unable to find an open issue addressing the problem, please [submit a new issue](https://github.com/jeremylong/DependencyCheck/issues/new).
- Please fill out the appropriate section of the bug report template provided. Please delete any sections not needed in the template.
## Reporting Vulnerabilities
- If you believe you have found a vulnerability in dependency-check itself (not that dependency-check found a vulnerability); please email jeremy.long@owasp.org.
## Asking Questions
- Your question may be answered by taking a look at the [documentataion](https://jeremylong.github.io/DependencyCheck/).
- If you still have a question consider:
- posting to the [Google Group](https://groups.google.com/forum/#!forum/dependency-check)
- opening a [new issue](https://github.com/jeremylong/DependencyCheck/issues/new)
## Enhancement Requests
- Suggest changes by [submitting a new issue](https://github.com/jeremylong/DependencyCheck/issues/new) and begin coding.
## Contributing Code
- If you have written a new feature or have fixed a bug please open a new pull request with the patch.
- Ensure the PR description clearly describes the problem and solution. Include any related issue number(s) if applicable.
- Please ensure the PR passes the automated checks performed (travis-ci, codacy, etc.)
- Please consider adding test cases for any new functionality
## Thank you for your contributions
OWASP dependency-check team

20
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,20 @@
Please delete any un-needed section from the following issue template:
### Reporting Bugs/Errors
When reporting errors, 99% of the time log file output is required. Please post the log file as a [gist](https://gist.github.com/) and provide a link in the new issue.
### Reporting False Positives
When reporting a false positive please include:
- The location of the dependency (Maven GAV, URL to download the dependency, etc.)
- The CPE that is believed to be false positive
- Please report the CPE not the CVE
#### Example
False positive on library foo.jar - reported as cpe:/a:apache:tomcat:7.0
```xml
<dependency>
<groupId>org.sample</groupId>
<artifactId>foo</artifactId>
<version>1.0</version>
</dependency>
```

9
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,9 @@
## Fixes Issue #
## Description of Change
*Please add a description of the proposed change*
## Have test cases been added to cover the new functionality?
*yes/no*

2
.gitignore vendored
View File

@@ -26,3 +26,5 @@ _site/**
.LCKpom.xml~
#coverity
/cov-int/
/dependency-check-core/nbproject/
cov-scan.bat

13
.travis.yml Normal file
View File

@@ -0,0 +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

29
Dockerfile Normal file
View File

@@ -0,0 +1,29 @@
FROM java:8
MAINTAINER Timo Pagel <dependencycheckmaintainer@timo-pagel.de>
ENV user=dependencycheck
ENV version_url=https://jeremylong.github.io/DependencyCheck/current.txt
ENV download_url=https://dl.bintray.com/jeremy-long/owasp
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/
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
CMD ["--help"]
ENTRYPOINT ["/usr/share/dependency-check/bin/dependency-check.sh"]

View File

@@ -1,3 +1,7 @@
[![Build Status](https://travis-ci.org/jeremylong/DependencyCheck.svg?branch=master)](https://travis-ci.org/jeremylong/DependencyCheck) [![Coverity Scan Build Status](https://scan.coverity.com/projects/1654/badge.svg)](https://scan.coverity.com/projects/dependencycheck) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/6b6021d481dc41a888c5da0d9ecf9494)](https://www.codacy.com/app/jeremylong/DependencyCheck?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=jeremylong/DependencyCheck&amp;utm_campaign=Badge_Grade) [![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.txt)
[![Black Hat Arsenal](https://www.toolswatch.org/badges/arsenal/2015.svg)](https://www.toolswatch.org/2015/06/black-hat-arsenal-usa-2015-speakers-lineup/) [![Black Hat Arsenal](https://www.toolswatch.org/badges/arsenal/2014.svg)](https://www.toolswatch.org/2014/06/black-hat-usa-2014-arsenal-tools-speaker-list/) [![Black Hat Arsenal](https://www.toolswatch.org/badges/arsenal/2013.svg)](https://www.toolswatch.org/2013/06/announcement-blackhat-arsenal-usa-2013-selected-tools/)
Dependency-Check
================
@@ -9,7 +13,7 @@ Current Releases
-------------
### Jenkins Plugin
For instructions on the use of the Jenkins plugin please see the [Jenkins dependency-check page](http://wiki.jenkins-ci.org/x/CwDgAQ).
For instructions on the use of the Jenkins plugin please see the [OWASP Dependency-Check Plugin page](https://wiki.jenkins-ci.org/display/JENKINS/OWASP+Dependency-Check+Plugin).
### Command Line
@@ -21,23 +25,23 @@ The latest CLI can be downloaded from bintray's
On *nix
```
$ ./bin/dependency-check.sh -h
$ ./bin/dependency-check.sh --app Testing --out . --scan [path to jar files to be scanned]
$ ./bin/dependency-check.sh --project Testing --out . --scan [path to jar files to be scanned]
```
On Windows
```
> bin/dependency-check.bat -h
> bin/dependency-check.bat --app 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)
```
$ brew update && brew install dependency-check
$ dependency-check -h
$ dependency-check --app Testing --out . --scan [path to jar files to be scanned]
$ dependency-check --project Testing --out . --scan [path to jar files to be scanned]
```
### Maven Plugin
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/usage.html).
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven).
The plugin can be configured using the following:
```xml
@@ -66,7 +70,7 @@ The plugin can be configured using the following:
### Ant Task
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/installation.html).
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-ant).
Development Usage
-------------
@@ -84,17 +88,54 @@ On *nix
```
$ mvn install
$ ./dependency-check-cli/target/release/bin/dependency-check.sh -h
$ ./dependency-check-cli/target/release/bin/dependency-check.sh --app Testing --out . --scan ./src/test/resources
$ ./dependency-check-cli/target/release/bin/dependency-check.sh --project Testing --out . --scan ./src/test/resources
```
On Windows
```
> mvn install
> dependency-check-cli/target/release/bin/dependency-check.bat -h
> dependency-check-cli/target/release/bin/dependency-check.bat --app 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 current working directory. Persistent data and report directories are used, allowing you to destroy the container after running.
```
#!/bin/sh
OWASPDC_DIRECTORY=$HOME/OWASP-Dependency-Check
DATA_DIRECTORY="$OWASPDC_DIRECTORY/data"
REPORT_DIRECTORY="$OWASPDC_DIRECTORY/reports"
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
# 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 \
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"
```
Mailing List
------------
@@ -107,14 +148,14 @@ Archive: [google group](https://groups.google.com/forum/#!forum/dependency-check
Copyright & License
-
Dependency-Check is Copyright (c) 2012-2015 Jeremy Long. All Rights Reserved.
Dependency-Check is Copyright (c) 2012-2016 Jeremy Long. All Rights Reserved.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-cli/blob/master/LICENSE.txt) file for the full license.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/LICENSE.txt) file for the full license.
Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt] [notices] file for more information.
Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt][notices] file for more information.
[wiki]: https://github.com/jeremylong/DependencyCheck/wiki
[subscribe]: mailto:dependency-check+subscribe@googlegroups.com
[post]: mailto:dependency-check@googlegroups.com
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICE.txt

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

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
This file is part of dependency-check-gradle.
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.
@@ -14,18 +14,19 @@ 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) 2015 Jeremy Long. All Rights Reserved.
Copyright (c) 2017 Jeremy Long. All Rights Reserved.
-->
<project name="dependency-check-gradle">
<bannerLeft>
<name>OWASP dependency-check-gradle</name>
<alt>OWASP dependency-check-gradle</alt>
<src>./images/dc-gradle.svg</src>
<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

@@ -1,9 +1,6 @@
-----------------------------
---begin dependency-check----
-----------------------------
dependency-check
OWASP dependency-check
Copyright (c) 2012-2013 Jeremy Long. All Rights Reserved.
Copyright (c) 2012-2015 Jeremy Long. All Rights Reserved.
The licenses for the software listed below can be found in the META-INF/licenses/[dependency name].
@@ -19,11 +16,3 @@ An original copy of the license agreement can be found at: http://www.h2database
This product includes data from the Common Weakness Enumeration (CWE): http://cwe.mitre.org/
This product downloads and utilizes data from the National Vulnerability Database hosted by NIST: http://nvd.nist.gov/download.cfm
-----------------------------
---end dependency-check------
-----------------------------
Notices below are from dependent libraries and have been included via maven-shade-plugin.
-----------------------------

View File

@@ -6,7 +6,7 @@ performed are a "best effort" and as such, there could be false positives as wel
vulnerabilities in 3rd party components is a well-known problem and is currently documented in the 2013 OWASP
Top 10 as [A9 - Using Components with Known Vulnerabilities](https://www.owasp.org/index.php/Top_10_2013-A9-Using_Components_with_Known_Vulnerabilities).
Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/installation.html).
Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-ant/index.html).
Mailing List
------------
@@ -20,6 +20,6 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-cli/blob/master/LICENSE.txt) file for the full license.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/LICENSE.txt) file for the full license.
Dependency-Check-Ant makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-ant/blob/master/NOTICES.txt) file for more information.
Dependency-Check-Ant makes use of other open source libraries. Please see the [NOTICE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/dependency-check-ant/NOTICE.txt) file for more information.

View File

@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.0</version>
<version>1.4.6-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-ant</artifactId>
@@ -190,179 +190,43 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/NOTICE.txt</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>META-INF/NOTICE</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>META-INF/LICENSE</resource>
</transformer>
</transformers>
<attach>false</attach> <!-- don't install/deploy this archive -->
</configuration>
<executions>
<execution>
<id>create-distribution</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/release.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</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>
</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>
<systemProperties>
<property>
<name>data.directory</name>
<value>${project.build.directory}/dependency-check-data</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${reporting.project-info-reports-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>summary</report>
<report>license</report>
<report>help</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${reporting.javadoc-plugin.version}</version>
<configuration>
<failOnError>false</failOnError>
<bottom>Copyright© 2012-15 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${reporting.versions-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>dependency-updates-report</report>
<report>plugin-updates-report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>${reporting.jxr-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${reporting.cobertura-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${reporting.surefire-report-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>taglist-maven-plugin</artifactId>
<version>${reporting.taglist-plugin.version}</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>Todo Work</displayName>
<tags>
<tag>
<matchString>todo</matchString>
<matchType>ignoreCase</matchType>
</tag>
<tag>
<matchString>FIXME</matchString>
<matchType>exact</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -382,7 +246,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<version>${reporting.pmd-plugin.version}</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<linkXRef>true</linkXRef>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/generated/*.java</exclude>
@@ -395,11 +259,6 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
</rulesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>${reporting.findbugs-plugin.version}</version>
</plugin>
</plugins>
</reporting>
<dependencies>
@@ -423,6 +282,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>

View File

@@ -12,18 +12,25 @@
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!--fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<outputDirectory>dependency-check</outputDirectory>
<directory>${project.build.directory}</directory>
<includes>
<include>dependency-check*.jar</include>
</includes>
</fileSet>
</fileSets>
</fileSets-->
<files>
<file>
<source>${project.build.directory}/${project.artifactId}-${project.version}.jar</source>
<outputDirectory>dependency-check-ant</outputDirectory>
<destName>dependency-check-ant.jar</destName>
</file>
</files>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<outputDirectory>dependency-check-ant/lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>

View File

@@ -24,16 +24,21 @@ import org.slf4j.helpers.MarkerIgnoringBase;
import org.slf4j.helpers.MessageFormatter;
/**
* An instance of {@link org.slf4j.Logger} which simply calls the log method on the delegate Ant task
* An instance of {@link org.slf4j.Logger} which simply calls the log method on
* the delegate Ant task.
*
* @author colezlaw
*/
public class AntLoggerAdapter extends MarkerIgnoringBase {
/**
* serialization UID.
*/
private static final long serialVersionUID = -1337;
/**
* A reference to the Ant task used for logging.
*/
private Task task;
private transient Task task;
/**
* Constructs an Ant Logger Adapter.
@@ -63,7 +68,9 @@ public class AntLoggerAdapter extends MarkerIgnoringBase {
@Override
public void trace(String msg) {
task.log(msg, Project.MSG_VERBOSE);
if (task != null) {
task.log(msg, Project.MSG_VERBOSE);
}
}
@Override

View File

@@ -0,0 +1,166 @@
/*
* This file is part of dependency-check-ant.
*
* 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) 2015 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.taskdefs;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.impl.StaticLoggerBinder;
/**
* An Ant task definition to execute dependency-check during an Ant build.
*
* @author Jeremy Long
*/
public class Purge extends Task {
/**
* The properties file location.
*/
private static final String PROPERTIES_FILE = "task.properties";
/**
* Construct a new DependencyCheckTask.
*/
public Purge() {
super();
// Call this before Dependency Check Core starts logging anything - this way, all SLF4J messages from
// core end up coming through this tasks logger
StaticLoggerBinder.getSingleton().setTask(this);
}
/**
* The location of the data directory that contains
*/
private String dataDirectory = null;
/**
* Get the value of dataDirectory.
*
* @return the value of dataDirectory
*/
public String getDataDirectory() {
return dataDirectory;
}
/**
* Set the value of dataDirectory.
*
* @param dataDirectory new value of dataDirectory
*/
public void setDataDirectory(String dataDirectory) {
this.dataDirectory = dataDirectory;
}
/**
* Indicates if dependency-check should fail the build if an exception
* occurs.
*/
private boolean failOnError = true;
/**
* Get the value of failOnError.
*
* @return the value of failOnError
*/
public boolean isFailOnError() {
return failOnError;
}
/**
* Set the value of failOnError.
*
* @param failOnError new value of failOnError
*/
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
/**
* Executes the dependency-check purge to delete the existing local copy of
* the NVD CVE data.
*
* @throws BuildException thrown if there is a problem deleting the file(s)
*/
@Override
public void execute() throws BuildException {
populateSettings();
File db;
try {
db = new File(Settings.getDataDirectory(), "dc.h2.db");
if (db.exists()) {
if (db.delete()) {
log("Database file purged; local copy of the NVD has been removed", Project.MSG_INFO);
} else {
final String msg = String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath());
if (this.failOnError) {
throw new BuildException(msg);
}
log(msg, Project.MSG_ERR);
}
} else {
final String msg = String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath());
if (this.failOnError) {
throw new BuildException(msg);
}
log(msg, Project.MSG_ERR);
}
} catch (IOException ex) {
final String msg = "Unable to delete the database";
if (this.failOnError) {
throw new BuildException(msg);
}
log(msg, Project.MSG_ERR);
} finally {
Settings.cleanup(true);
}
}
/**
* Takes the properties supplied and updates the dependency-check settings.
* Additionally, this sets the system properties required to change the
* proxy server, port, and connection timeout.
*
* @throws BuildException thrown if the properties file cannot be read.
*/
protected void populateSettings() throws BuildException {
Settings.initialize();
try (InputStream taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE)) {
Settings.mergeProperties(taskProperties);
} catch (IOException ex) {
final String msg = "Unable to load the dependency-check ant task.properties file.";
if (this.failOnError) {
throw new BuildException(msg, ex);
}
log(msg, ex, Project.MSG_WARN);
}
if (dataDirectory != null) {
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
} else {
final File jarPath = new File(Purge.class.getProtectionDomain().getCodeSource().getLocation().getPath());
final File base = jarPath.getParentFile();
final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
final File dataDir = new File(base, sub);
Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
}
}
}

View File

@@ -0,0 +1,445 @@
/*
* This file is part of dependency-check-ant.
*
* 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) 2015 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.taskdefs;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.impl.StaticLoggerBinder;
/**
* An Ant task definition to execute dependency-check update. This will download
* the latest data from the National Vulnerability Database (NVD) and store a
* copy in the local database.
*
* @author Jeremy Long
*/
public class Update extends Purge {
/**
* The Proxy Server.
*/
private String proxyServer;
/**
* The Proxy Port.
*/
private String proxyPort;
/**
* The Proxy username.
*/
private String proxyUsername;
/**
* The Proxy password.
*/
private String proxyPassword;
/**
* The Connection Timeout.
*/
private String connectionTimeout;
/**
* The database driver name; such as org.h2.Driver.
*/
private String databaseDriverName;
/**
* The path to the database driver JAR file if it is not on the class path.
*/
private String databaseDriverPath;
/**
* The database connection string.
*/
private String connectionString;
/**
* The user name for connecting to the database.
*/
private String databaseUser;
/**
* The password to use when connecting to the database.
*/
private String databasePassword;
/**
* The url for the modified NVD CVE (1.2 schema).
*/
private String cveUrl12Modified;
/**
* Base Data Mirror URL for CVE 1.2.
*/
private String cveUrl12Base;
/**
* Data Mirror URL for CVE 2.0.
*/
private String cveUrl20Base;
/**
* The number of hours to wait before re-checking for updates.
*/
private Integer cveValidForHours;
/**
* The url for the modified NVD CVE (2.0 schema).
*/
private String cveUrl20Modified;
/**
* Construct a new UpdateTask.
*/
public Update() {
super();
// Call this before Dependency Check Core starts logging anything - this way, all SLF4J messages from
// core end up coming through this tasks logger
StaticLoggerBinder.getSingleton().setTask(this);
}
/**
* Get the value of proxyServer.
*
* @return the value of proxyServer
*/
public String getProxyServer() {
return proxyServer;
}
/**
* Set the value of proxyServer.
*
* @param server new value of proxyServer
*/
public void setProxyServer(String server) {
this.proxyServer = server;
}
/**
* Get the value of proxyPort.
*
* @return the value of proxyPort
*/
public String getProxyPort() {
return proxyPort;
}
/**
* Set the value of proxyPort.
*
* @param proxyPort new value of proxyPort
*/
public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
}
/**
* Get the value of proxyUsername.
*
* @return the value of proxyUsername
*/
public String getProxyUsername() {
return proxyUsername;
}
/**
* Set the value of proxyUsername.
*
* @param proxyUsername new value of proxyUsername
*/
public void setProxyUsername(String proxyUsername) {
this.proxyUsername = proxyUsername;
}
/**
* Get the value of proxyPassword.
*
* @return the value of proxyPassword
*/
public String getProxyPassword() {
return proxyPassword;
}
/**
* Set the value of proxyPassword.
*
* @param proxyPassword new value of proxyPassword
*/
public void setProxyPassword(String proxyPassword) {
this.proxyPassword = proxyPassword;
}
/**
* Get the value of connectionTimeout.
*
* @return the value of connectionTimeout
*/
public String getConnectionTimeout() {
return connectionTimeout;
}
/**
* Set the value of connectionTimeout.
*
* @param connectionTimeout new value of connectionTimeout
*/
public void setConnectionTimeout(String connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
/**
* Get the value of databaseDriverName.
*
* @return the value of databaseDriverName
*/
public String getDatabaseDriverName() {
return databaseDriverName;
}
/**
* Set the value of databaseDriverName.
*
* @param databaseDriverName new value of databaseDriverName
*/
public void setDatabaseDriverName(String databaseDriverName) {
this.databaseDriverName = databaseDriverName;
}
/**
* Get the value of databaseDriverPath.
*
* @return the value of databaseDriverPath
*/
public String getDatabaseDriverPath() {
return databaseDriverPath;
}
/**
* Set the value of databaseDriverPath.
*
* @param databaseDriverPath new value of databaseDriverPath
*/
public void setDatabaseDriverPath(String databaseDriverPath) {
this.databaseDriverPath = databaseDriverPath;
}
/**
* Get the value of connectionString.
*
* @return the value of connectionString
*/
public String getConnectionString() {
return connectionString;
}
/**
* Set the value of connectionString.
*
* @param connectionString new value of connectionString
*/
public void setConnectionString(String connectionString) {
this.connectionString = connectionString;
}
/**
* Get the value of databaseUser.
*
* @return the value of databaseUser
*/
public String getDatabaseUser() {
return databaseUser;
}
/**
* Set the value of databaseUser.
*
* @param databaseUser new value of databaseUser
*/
public void setDatabaseUser(String databaseUser) {
this.databaseUser = databaseUser;
}
/**
* Get the value of databasePassword.
*
* @return the value of databasePassword
*/
public String getDatabasePassword() {
return databasePassword;
}
/**
* Set the value of databasePassword.
*
* @param databasePassword new value of databasePassword
*/
public void setDatabasePassword(String databasePassword) {
this.databasePassword = databasePassword;
}
/**
* Get the value of cveUrl12Modified.
*
* @return the value of cveUrl12Modified
*/
public String getCveUrl12Modified() {
return cveUrl12Modified;
}
/**
* Set the value of cveUrl12Modified.
*
* @param cveUrl12Modified new value of cveUrl12Modified
*/
public void setCveUrl12Modified(String cveUrl12Modified) {
this.cveUrl12Modified = cveUrl12Modified;
}
/**
* Get the value of cveUrl20Modified.
*
* @return the value of cveUrl20Modified
*/
public String getCveUrl20Modified() {
return cveUrl20Modified;
}
/**
* Set the value of cveUrl20Modified.
*
* @param cveUrl20Modified new value of cveUrl20Modified
*/
public void setCveUrl20Modified(String cveUrl20Modified) {
this.cveUrl20Modified = cveUrl20Modified;
}
/**
* Get the value of cveUrl12Base.
*
* @return the value of cveUrl12Base
*/
public String getCveUrl12Base() {
return cveUrl12Base;
}
/**
* Set the value of cveUrl12Base.
*
* @param cveUrl12Base new value of cveUrl12Base
*/
public void setCveUrl12Base(String cveUrl12Base) {
this.cveUrl12Base = cveUrl12Base;
}
/**
* Get the value of cveUrl20Base.
*
* @return the value of cveUrl20Base
*/
public String getCveUrl20Base() {
return cveUrl20Base;
}
/**
* Set the value of cveUrl20Base.
*
* @param cveUrl20Base new value of cveUrl20Base
*/
public void setCveUrl20Base(String cveUrl20Base) {
this.cveUrl20Base = cveUrl20Base;
}
/**
* Get the value of cveValidForHours.
*
* @return the value of cveValidForHours
*/
public Integer getCveValidForHours() {
return cveValidForHours;
}
/**
* Set the value of cveValidForHours.
*
* @param cveValidForHours new value of cveValidForHours
*/
public void setCveValidForHours(Integer cveValidForHours) {
this.cveValidForHours = cveValidForHours;
}
/**
* Executes the update by initializing the settings, downloads the NVD XML
* data, and then processes the data storing it in the local database.
*
* @throws BuildException thrown if a connection to the local database
* cannot be made.
*/
@Override
public void execute() throws BuildException {
populateSettings();
Engine engine = null;
try {
engine = new Engine(Update.class.getClassLoader());
try {
engine.doUpdates();
} catch (UpdateException ex) {
if (this.isFailOnError()) {
throw new BuildException(ex);
}
log(ex.getMessage(), Project.MSG_ERR);
}
} catch (DatabaseException ex) {
final String msg = "Unable to connect to the dependency-check database; unable to update the NVD data";
if (this.isFailOnError()) {
throw new BuildException(msg, ex);
}
log(msg, Project.MSG_ERR);
} finally {
Settings.cleanup(true);
if (engine != null) {
engine.cleanup();
}
}
}
/**
* Takes the properties supplied and updates the dependency-check settings.
* Additionally, this sets the system properties required to change the
* proxy server, port, and connection timeout.
*
* @throws BuildException thrown when an invalid setting is configured.
*/
@Override
protected void populateSettings() throws BuildException {
super.populateSettings();
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUsername);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
if (cveValidForHours != null) {
if (cveValidForHours >= 0) {
Settings.setInt(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
} else {
throw new BuildException("Invalid setting: `cpeValidForHours` must be 0 or greater");
}
}
}
}

View File

@@ -23,18 +23,25 @@ import org.slf4j.ILoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
/**
* The binding of {@link LoggerFactory} class with an actual instance of {@link ILoggerFactory} is performed using information
* returned by this class.
* The binding of org.slf4j.LoggerFactory class with an actual instance of
* org.slf4j.ILoggerFactory is performed using information returned by this
* class.
*
* @author colezlaw
*/
//CSOFF: FinalClass
public class StaticLoggerBinder implements LoggerFactoryBinder {
//CSON: FinalClass
/**
* The unique instance of this class
*
*/
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
/**
* Ant tasks have the log method we actually want to call. So we hang onto
* the task as a delegate
*/
private Task task = null;
/**
* Return the singleton of this class.
@@ -45,11 +52,6 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
return SINGLETON;
}
/**
* Ant tasks have the log method we actually want to call. So we hang onto the task as a delegate
*/
private Task task = null;
/**
* Set the Task which will this is to log through.
*
@@ -61,16 +63,24 @@ public class StaticLoggerBinder implements LoggerFactoryBinder {
}
/**
* Declare the version of the SLF4J API this implementation is compiled against. The value of this filed is usually modified
* with each release.
* Declare the version of the SLF4J API this implementation is compiled
* against. The value of this filed is usually modified with each release.
*/
// to avoid constant folding by the compiler, this field must *not* be final
//CSOFF: StaticVariableName
//CSOFF: VisibilityModifier
public static String REQUESTED_API_VERSION = "1.7.12"; // final
//CSON: VisibilityModifier
//CSON: StaticVariableName
/**
* The logger factory class string.
*/
private static final String LOGGER_FACTORY_CLASS = AntLoggerFactory.class.getName();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory} method should always be the smae object
* The ILoggerFactory instance returned by the {@link #getLoggerFactory}
* method should always be the smae object
*/
private ILoggerFactory loggerFactory;

View File

@@ -0,0 +1,3 @@
dependency-check=org.owasp.dependencycheck.taskdefs.Check
dependency-check-purge=org.owasp.dependencycheck.taskdefs.Purge
dependency-check-update=org.owasp.dependencycheck.taskdefs.Update

View File

@@ -1,2 +1,2 @@
# the path to the data directory
data.directory=dependency-check-data
data.directory=data/3.0

View File

@@ -1,3 +0,0 @@
# define custom tasks here
dependencycheck=org.owasp.dependencycheck.taskdefs.DependencyCheckTask

View File

@@ -0,0 +1,20 @@
Configuration
====================
The dependency-check-purge task deletes the local copy of the NVD. This task
should rarely be used, if ever. This is included as a convenience method in
the rare circumstance that the local H2 database becomes corrupt.
```xml
<target name="dependency-check-purge" description="Dependency-Check purge">
<dependency-check-purge />
</target>
```
Configuration: dependency-check-purge Task
--------------------
The following properties can be set on the dependency-check-purge task.
Property | Description | Default Value
----------------------|------------------------------------------------------------------------|------------------
dataDirectory | Data directory that is used to store the local copy of the NVD | data
failOnError | Whether the build should fail if there is an error executing the purge | true

View File

@@ -0,0 +1,45 @@
Configuration
====================
The dependency-check-update task downloads and updates the local copy of the NVD.
There are several reasons that one may want to use this task; primarily, creating
an update that will be run only once a day or once every few days (but not greater
than 7 days) and then use the `autoUpdate="false"` setting on individual
dependency-check scans. See [Internet Access Required](https://jeremylong.github.io/DependencyCheck/data/index.html)
for more information on why this task would be used.
```xml
<target name="dependency-check-update" description="Dependency-Check Update">
<dependency-check-update />
</target>
```
Configuration: dependency-check-update Task
--------------------
The following properties can be set on the dependency-check task.
Property | Description | Default Value
----------------------|------------------------------------|------------------
proxyServer | The Proxy Server. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
failOnError | Whether the build should fail if there is an error executing the update | true
Advanced Configuration
====================
The following properties can be configured in the plugin. However, they are less frequently changed. One exception
may be the cvedUrl properties, which can be used to host a mirror of the NVD within an enterprise environment.
Property | Description | Default Value
---------------------|-------------------------------------------------------------------------------------------------------|------------------
cveUrl12Modified | URL for the modified CVE 1.2. | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
cveUrl20Modified | URL for the modified CVE 2.0. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | https://nvd.nist.gov/download/nvdcve-%d.xml.gz
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
dataDirectory | Data directory that is used to store the local copy of the NVD. This should generally not be changed. | data
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp;
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp;
connectionString | The connection string used to connect to the database. | &nbsp;
databaseUser | The username used when connecting to the database. | &nbsp;
databasePassword | The password used when connecting to the database. | &nbsp;

View File

@@ -1,5 +1,11 @@
Configuration
====================
Once dependency-check-ant has been [installed](index.html) the defined tasks can be used.
* dependency-check - the primary task used to check the project dependencies. Configuration options are below.
* dependency-check-purge - deletes the local copy of the NVD; this should rarely be used (if ever). See the [purge configuration](config-purge.html) for more information.
* dependency-check-update - downloads and updates the local copy of the NVD. See the [update configuration](config-update.html) for more information.
To configure the dependency-check task you can add it to a target and include a
file based [resource collection](http://ant.apache.org/manual/Types/resources.html#collection)
such as a [FileSet](http://ant.apache.org/manual/Types/fileset.html), [DirSet](http://ant.apache.org/manual/Types/dirset.html),
@@ -8,7 +14,7 @@ the project's dependencies.
```xml
<target name="dependency-check" description="Dependency-Check Analysis">
<dependency-check applicationname="Hello World"
<dependency-check projectname="Hello World"
reportoutputdirectory="${basedir}"
reportformat="ALL">
@@ -19,24 +25,27 @@ the project's dependencies.
</target>
```
Configuration
====================
The following properties can be set on the dependency-check-maven plugin.
Configuration: dependency-check Task
--------------------
The following properties can be set on the dependency-check task.
Property | Description | Default Value
----------------------|------------------------------------|------------------
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
updateOnly | If set to true only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. | false
externalReport | When using as a Site plugin this parameter sets whether or not the external report format should be used. | false
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'
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
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
suppressionFile | The file path to the XML suppression file \- used to suppress [false positives](../general/suppression.html) | &nbsp;
proxyServer | The Proxy Server. | &nbsp;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
Property | Description | Default Value
----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD | 4
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, 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;
proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
enableExperimental | Enable the [experimental analyzers](../analyzers/index.html). If not enabled the experimental analyzers (see below) will not be loaded or used. | false
Analyzer Configuration
====================
@@ -46,18 +55,30 @@ Note, that specific analyzers will automatically disable themselves if no file
types that they support are detected - so specifically disabling them may not
be needed.
Property | Description | Default Value
------------------------|---------------------------------------------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
nexusUrl | Defines the Nexus web service endpoint (example http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | &nbsp;
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
assemblyAnalyzerEnabled | Sets whether or not the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Property | Description | Default Value
------------------------------|-----------------------------------------------------------------------------------|------------------
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
nexusUrl | Defines the Nexus web service endpoint (example http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | &nbsp;
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
pyDistributionAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | true
pyPackageAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | true
rubygemsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | true
opensslAnalyzerEnabled | Sets whether the openssl Analyzer should be used. | true
cmakeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) CMake Analyzer should be used. | true
autoconfAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) autoconf Analyzer should be used. | true
composerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer should be used. | true
nodeAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Node.js Analyzer should be used. | true
nuspecAnalyzerEnabled | Sets whether the .NET Nuget Nuspec Analyzer will be used. | true
cocoapodsAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer should be used. | true
bundleAuditAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Bundle Audit Analyzer should be used. | true
bundleAuditPath | Sets the path to the bundle audit executable; only used if bundle audit analyzer is enabled and experimental analyzers are enabled. | &nbsp;
swiftPackageManagerAnalyzerEnabled | Sets whether the [experimental](../analyzers/index.html) Switft Package Analyzer should be used. | true
assemblyAnalyzerEnabled | Sets whether the .NET Assembly Analyzer should be used. | true
pathToMono | The path to Mono for .NET assembly analysis on non-windows systems. | &nbsp;
Advanced Configuration
====================
@@ -70,7 +91,7 @@ cveUrl12Modified | URL for the modified CVE 1.2.
cveUrl20Modified | URL for the modified CVE 2.0. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
cveUrl12Base | Base URL for each year's CVE 1.2, the %d will be replaced with the year. | http://nvd.nist.gov/download/nvdcve-%d.xml
cveUrl20Base | Base URL for each year's CVE 2.0, the %d will be replaced with the year. | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
dataDirectory | Data directory to hold SQL CVEs contents. This should generally not be changed. | &nbsp;
dataDirectory | Data directory that is used to store the local copy of the NVD. This should generally not be changed. | data
databaseDriverName | The name of the database driver. Example: org.h2.Driver. | &nbsp;
databaseDriverPath | The path to the database driver JAR file; only used if the driver is not in the class path. | &nbsp;
connectionString | The connection string used to connect to the database. | &nbsp;

View File

@@ -7,23 +7,28 @@ identifiers, and the associated Common Vulnerability and Exposure (CVE) entries.
Installation
====================
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}.jar).
To install dependency-check-ant place the dependency-check-ant-${project.version}.jar into
the lib directory of your Ant instalation directory. Once installed you can add
the taskdef to you build.xml and add the task to a new or existing target:
1. Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}-release.zip).
2. Unzip the archive
3. Add the taskdef to your build.xml:
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
```
```xml
<!-- Set the value to the installation directory's path -->
<property name="dependency-check.home" value="C:/tools/dependency-check-ant"/>
<path id="dependency-check.path">
<pathelement location="${dependency-check.home}/dependency-check-ant.jar"/>
<fileset dir="${dependency-check.home}/lib">
<include name="*.jar"/>
</fileset>
</path>
<taskdef resource="dependency-check-taskdefs.properties">
<classpath refid="dependency-check.path" />
</taskdef>
```
4. Use the defined taskdefs:
* [dependency-check](configuration.html) - the primary task used to check the project dependencies.
* [dependency-check-purge](config-purge.html) - deletes the local copy of the NVD; this should rarely be used (if ever).
* [dependency-check-update](config-update.html) - downloads and updates the local copy of the NVD.
If you do not want to install dependency-check-ant into your ant's lib directory when you define the task def you
must add the classpath to the taskdef:
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
</taskdef>
```
It is important to understand that the first time this task is executed it may
take 10 minutes or more as it downloads and processes the data from the National

View File

@@ -1,33 +0,0 @@
Usage
====================
First, add the dependency-check-ant taskdef to your build.xml (see the [installation guide](installation.html)):
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask"/>
```
Or
```xml
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask">
<classpath path="[path]/[to]/dependency-check-ant-${project.version}.jar"/>
</taskdef>
```
Next, add the task to a target of your choosing:
```xml
<target name="dependency-check" description="Dependency-Check Analysis">
<dependency-check applicationname="Hello World"
autoupdate="true"
reportoutputdirectory="${basedir}"
reportformat="HTML">
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</dependency-check>
</target>
```
See the [configuration guide](configuration.html) for more information.

View File

@@ -27,8 +27,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<item name="dependency-check" href="../index.html"/>
</breadcrumbs>
<menu name="Getting Started">
<item name="Installation" href="installation.html"/>
<item name="Usage" href="usage.html"/>
<item name="Installation" href="index.html"/>
<item name="Configuration" href="configuration.html"/>
</menu>
<menu ref="reports" />

View File

@@ -26,12 +26,11 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.utils.Settings;
import static org.junit.Assert.assertTrue;
/**
*
* @author Jeremy Long
@@ -65,15 +64,11 @@ public class DependencyCheckTaskTest {
@Test
public void testAddFileSet() throws Exception {
File report = new File("target/dependency-check-report.html");
if (report.exists()) {
if (!report.delete()) {
throw new Exception("Unable to delete 'target/DependencyCheck-Report.html' prior to test.");
}
if (report.exists() && !report.delete()) {
throw new Exception("Unable to delete 'target/DependencyCheck-Report.html' prior to test.");
}
buildFileRule.executeTarget("test.fileset");
assertTrue("DependencyCheck report was not generated", report.exists());
}
/**

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="Dependency-Check Test Build" default="test.fileset" basedir=".">
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.DependencyCheckTask" />
<taskdef name="dependency-check" classname="org.owasp.dependencycheck.taskdefs.Check" />
<target name="test.fileset">
<dependency-check
@@ -61,11 +61,14 @@
<target name="failCVSS">
<dependency-check
applicationName="test formatBAD"
applicationName="test failCVSS"
reportOutputDirectory="${project.build.directory}"
reportFormat="XML"
autoupdate="false"
failBuildOnCVSS="8">
failBuildOnCVSS="3">
<fileset dir="${project.build.directory}/test-classes/jars">
<include name="axis-1.4.jar"/>
</fileset>
</dependency-check>
</target>
</project>

View File

@@ -5,7 +5,7 @@ performed are a "best effort" and as such, there could be false positives as wel
vulnerabilities in 3rd party components is a well-known problem and is currently documented in the 2013 OWASP
Top 10 as [A9 - Using Components with Known Vulnerabilities](https://www.owasp.org/index.php/Top_10_2013-A9-Using_Components_with_Known_Vulnerabilities).
Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-cli/installation.html).
Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-cli/index.html).
Mailing List
------------
@@ -19,6 +19,6 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-cli/blob/master/LICENSE.txt) file for the full license.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/LICENSE.txt) file for the full license.
Dependency-Check Command Line makes use of other open source libraries. Please see the [NOTICE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-cli/blob/master/NOTICES.txt) file for more information.
Dependency-Check Command Line makes use of other open source libraries. Please see the [NOTICE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/dependency-check-cli/NOTICE.txt) file for more information.

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.0</version>
<version>1.4.6-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-cli</artifactId>
@@ -69,65 +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>
<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.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
@@ -143,6 +84,8 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<configurationDirectory>plugins/*</configurationDirectory>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
</configuration>
<executions>
<execution>
@@ -178,96 +121,6 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${reporting.project-info-reports-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>summary</report>
<report>license</report>
<report>help</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${reporting.javadoc-plugin.version}</version>
<configuration>
<failOnError>false</failOnError>
<bottom>Copyright<EFBFBD> 2012-15 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${reporting.versions-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>dependency-updates-report</report>
<report>plugin-updates-report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>${reporting.jxr-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${reporting.cobertura-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${reporting.surefire-report-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>taglist-maven-plugin</artifactId>
<version>${reporting.taglist-plugin.version}</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>Todo Work</displayName>
<tags>
<tag>
<matchString>todo</matchString>
<matchType>ignoreCase</matchType>
</tag>
<tag>
<matchString>FIXME</matchString>
<matchType>exact</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -287,7 +140,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<version>${reporting.pmd-plugin.version}</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<linkXRef>true</linkXRef>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/generated/*.java</exclude>
@@ -300,11 +153,6 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
</rulesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>${reporting.findbugs-plugin.version}</version>
</plugin>
</plugins>
</reporting>
<dependencies>
@@ -334,5 +182,15 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@@ -29,6 +29,13 @@
<outputDirectory>dependency-check/repo</outputDirectory>
<directory>${project.build.directory}/release/repo</directory>
</fileSet>
<fileSet>
<directory>.</directory>
<outputDirectory>dependency-check/plugins</outputDirectory>
<excludes>
<exclude>*/**</exclude>
</excludes>
</fileSet>
<fileSet>
<outputDirectory>dependency-check</outputDirectory>
<includes>
@@ -53,21 +60,4 @@
</includes>
</fileSet>
</fileSets>
<!--
<fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<directory>${project.build.directory}</directory>
<includes>
<include>dependency-check*.jar</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
-->
</assembly>

View File

@@ -19,6 +19,7 @@ package org.owasp.dependencycheck;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -31,12 +32,17 @@ 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.dependency.Dependency;
import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.DirectoryScanner;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.core.FileAppender;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.slf4j.impl.StaticLoggerBinder;
/**
@@ -57,21 +63,26 @@ public class App {
* @param args the command line arguments
*/
public static void main(String[] args) {
int exitCode = 0;
try {
Settings.initialize();
final App app = new App();
app.run(args);
exitCode = app.run(args);
LOGGER.debug("Exit code: " + exitCode);
} finally {
Settings.cleanup(true);
}
System.exit(exitCode);
}
/**
* Main CLI entry-point into the application.
*
* @param args the command line arguments
* @return the exit code to return
*/
public void run(String[] args) {
public int run(String[] args) {
int exitCode = 0;
final CliParser cli = new CliParser();
try {
@@ -79,59 +90,146 @@ public class App {
} catch (FileNotFoundException ex) {
System.err.println(ex.getMessage());
cli.printHelp();
return;
return -1;
} catch (ParseException ex) {
System.err.println(ex.getMessage());
cli.printHelp();
return;
return -2;
}
if (cli.getVerboseLog() != null) {
prepareLogger(cli.getVerboseLog());
}
if (cli.isGetVersion()) {
if (cli.isPurge()) {
if (cli.getConnectionString() != null) {
LOGGER.error("Unable to purge the database when using a non-default connection string");
exitCode = -3;
} else {
try {
populateSettings(cli);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage());
LOGGER.debug("Error loading properties file", ex);
exitCode = -4;
}
File db;
try {
db = new File(Settings.getDataDirectory(), "dc.h2.db");
if (db.exists()) {
if (db.delete()) {
LOGGER.info("Database file purged; local copy of the NVD has been removed");
} else {
LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath());
exitCode = -5;
}
} else {
LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath());
exitCode = -6;
}
} catch (IOException ex) {
LOGGER.error("Unable to delete the database");
exitCode = -7;
}
}
} else if (cli.isGetVersion()) {
cli.printVersionInfo();
} else if (cli.isUpdateOnly()) {
populateSettings(cli);
runUpdateOnly();
} else if (cli.isRunScan()) {
populateSettings(cli);
try {
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(),
cli.getExcludeList(), cli.getSymLinkDepth());
populateSettings(cli);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage());
LOGGER.debug("Error loading properties file", ex);
exitCode = -4;
}
try {
runUpdateOnly();
} catch (UpdateException ex) {
LOGGER.error(ex.getMessage());
exitCode = -8;
} catch (DatabaseException ex) {
LOGGER.error(ex.getMessage());
exitCode = -9;
}
} else if (cli.isRunScan()) {
try {
populateSettings(cli);
} catch (InvalidSettingException ex) {
LOGGER.error(ex.getMessage());
LOGGER.debug("Error loading properties file", ex);
exitCode = -4;
}
try {
final String[] scanFiles = cli.getScanFiles();
if (scanFiles != null) {
exitCode = runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), scanFiles,
cli.getExcludeList(), cli.getSymLinkDepth(), cli.getFailOnCVSS());
} else {
LOGGER.error("No scan files configured");
}
} catch (InvalidScanPathException ex) {
LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
exitCode = -10;
} catch (DatabaseException ex) {
LOGGER.error(ex.getMessage());
exitCode = -11;
} catch (ReportException ex) {
LOGGER.error(ex.getMessage());
exitCode = -12;
} catch (ExceptionCollection ex) {
if (ex.isFatal()) {
exitCode = -13;
LOGGER.error("One or more fatal errors occurred");
} else {
exitCode = -14;
}
for (Throwable e : ex.getExceptions()) {
LOGGER.error(e.getMessage());
}
}
} else {
cli.printHelp();
}
return exitCode;
}
/**
* Scans the specified directories and writes the dependency reports to the reportDirectory.
* Scans the specified directories and writes the dependency reports to the
* reportDirectory.
*
* @param reportDirectory the path to the directory where the reports will be written
* @param reportDirectory the path to the directory where the reports will
* be written
* @param outputFormat the output format of the report
* @param applicationName the application name for the report
* @param files the files/directories to scan
* @param excludes the patterns for files/directories to exclude
* @param symLinkDepth the depth that symbolic links will be followed
* @param cvssFailScore the score to fail on if a vulnerability is found
* @return the exit code if there was an error
*
* @throws InvalidScanPathException thrown if the path to scan starts with "//"
* @throws InvalidScanPathException thrown if the path to scan starts with
* "//"
* @throws ReportException thrown when the report cannot be generated
* @throws DatabaseException thrown when there is an error connecting to the
* database
* @throws ExceptionCollection thrown when an exception occurs during
* analysis; there may be multiple exceptions contained within the
* collection.
*/
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
String[] excludes, int symLinkDepth) throws InvalidScanPathException {
private int runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
String[] excludes, int symLinkDepth, int cvssFailScore) throws InvalidScanPathException, DatabaseException,
ExceptionCollection, ReportException {
Engine engine = null;
int retCode = 0;
try {
engine = new Engine();
final List<String> antStylePaths = new ArrayList<String>();
final List<String> antStylePaths = new ArrayList<>();
for (String file : files) {
final String antPath = ensureCanonicalPath(file);
antStylePaths.add(antPath);
}
final Set<File> paths = new HashSet<File>();
final Set<File> paths = new HashSet<>();
for (String file : antStylePaths) {
LOGGER.debug("Scanning {}", file);
final DirectoryScanner scanner = new DirectoryScanner();
@@ -153,10 +251,9 @@ public class App {
include = "**/*";
}
}
//LOGGER.debug("baseDir: {}", baseDir);
//LOGGER.debug("include: {}", include);
scanner.setBasedir(baseDir);
scanner.setIncludes(include);
final String[] includes = {include};
scanner.setIncludes(includes);
scanner.setMaxLevelsOfSymlinks(symLinkDepth);
if (symLinkDepth <= 0) {
scanner.setFollowSymlinks(false);
@@ -175,34 +272,42 @@ public class App {
}
engine.scan(paths);
engine.analyzeDependencies();
final List<Dependency> dependencies = engine.getDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
ExceptionCollection exCol = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
LOGGER.debug("Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
if (ex.isFatal()) {
throw ex;
}
exCol = ex;
}
try {
engine.writeReports(applicationName, new File(reportDirectory), outputFormat);
} catch (ReportException ex) {
if (exCol != null) {
exCol.addException(ex);
throw exCol;
} else {
throw ex;
}
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
LOGGER.error("There was an IO error while attempting to generate the report.");
LOGGER.debug("", ex);
} catch (Throwable ex) {
LOGGER.error("There was an error while attempting to generate the report.");
LOGGER.debug("", ex);
if (exCol != null && exCol.getExceptions().size() > 0) {
throw exCol;
}
} catch (DatabaseException ex) {
LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.debug("", ex);
//Set the exit code based on whether we found a high enough vulnerability
for (Dependency dep : engine.getDependencies()) {
if (!dep.getVulnerabilities().isEmpty()) {
for (Vulnerability vuln : dep.getVulnerabilities()) {
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
if (vuln.getCvssScore() > cvssFailScore) {
retCode = 1;
}
}
}
}
return retCode;
} finally {
if (engine != null) {
engine.cleanup();
@@ -212,15 +317,16 @@ public class App {
/**
* Only executes the update phase of dependency-check.
*
* @throws UpdateException thrown if there is an error updating
* @throws DatabaseException thrown if a fatal error occurred and a
* connection to the database could not be established
*/
private void runUpdateOnly() {
private void runUpdateOnly() throws UpdateException, DatabaseException {
Engine engine = null;
try {
engine = new Engine();
engine.doUpdates();
} catch (DatabaseException ex) {
LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.debug("", ex);
} finally {
if (engine != null) {
engine.cleanup();
@@ -231,12 +337,13 @@ public class App {
/**
* Updates the global Settings.
*
* @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding settings in
* the core engine.
* @param cli a reference to the CLI Parser that contains the command line
* arguments used to set the corresponding settings in the core engine.
*
* @throws InvalidSettingException thrown when a user defined properties
* file is unable to be loaded.
*/
private void populateSettings(CliParser cli) {
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();
@@ -245,16 +352,7 @@ public class App {
final String dataDirectory = cli.getDataDirectory();
final File propertiesFile = cli.getPropertiesFile();
final String suppressionFile = cli.getSuppressionFile();
final boolean jarDisabled = cli.isJarDisabled();
final boolean archiveDisabled = cli.isArchiveDisabled();
final boolean pyDistDisabled = cli.isPythonDistributionDisabled();
final boolean cMakeDisabled = cli.isCmakeDisabled();
final boolean pyPkgDisabled = cli.isPythonPackageDisabled();
final boolean autoconfDisabled = cli.isAutoconfDisabled();
final boolean assemblyDisabled = cli.isAssemblyDisabled();
final boolean nuspecDisabled = cli.isNuspecDisabled();
final boolean centralDisabled = cli.isCentralDisabled();
final boolean nexusDisabled = cli.isNexusDisabled();
final String hintsFile = cli.getHintsFile();
final String nexusUrl = cli.getNexusUrl();
final String databaseDriverName = cli.getDatabaseDriverName();
final String databaseDriverPath = cli.getDatabaseDriverPath();
@@ -267,21 +365,22 @@ public class App {
final String cveMod20 = cli.getModifiedCve20Url();
final String cveBase12 = cli.getBaseCve12Url();
final String cveBase20 = cli.getBaseCve20Url();
final Integer cveValidForHours = cli.getCveValidForHours();
final Boolean autoUpdate = cli.isAutoUpdate();
final Boolean experimentalEnabled = cli.isExperimentalEnabled();
if (propertiesFile != null) {
try {
Settings.mergeProperties(propertiesFile);
} catch (FileNotFoundException ex) {
LOGGER.error("Unable to load properties file '{}'", propertiesFile.getPath());
LOGGER.debug("", ex);
throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
} catch (IOException ex) {
LOGGER.error("Unable to find properties file '{}'", propertiesFile.getPath());
LOGGER.debug("", ex);
throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
}
}
// 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);
@@ -295,64 +394,47 @@ 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);
if (proxyServer != null && !proxyServer.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
}
if (proxyUser != null && !proxyUser.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
}
if (proxyPass != null && !proxyPass.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
}
if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
}
if (suppressionFile != null && !suppressionFile.isEmpty()) {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
}
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);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPass);
Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
Settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
Settings.setIntIfNotNull(Settings.KEYS.CVE_CHECK_VALID_FOR_HOURS, cveValidForHours);
//File Type Analyzer Settings
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, !pyDistDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !pyPkgDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !autoconfDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cMakeDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled());
Settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, experimentalEnabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !centralDisabled);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
if (nexusUrl != null && !nexusUrl.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
}
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
}
if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
}
if (connectionString != null && !connectionString.isEmpty()) {
Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
}
if (databaseUser != null && !databaseUser.isEmpty()) {
Settings.setString(Settings.KEYS.DB_USER, databaseUser);
}
if (databasePassword != null && !databasePassword.isEmpty()) {
Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
}
if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
}
if (pathToMono != null && !pathToMono.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
}
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());
Settings.setBoolean(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, !cli.isPythonPackageDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, !cli.isAutoconfDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_CMAKE_ENABLED, !cli.isCmakeDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !cli.isNuspecDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !cli.isAssemblyDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, !cli.isBundleAuditDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, !cli.isOpenSSLDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, !cli.isComposerDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, !cli.isNodeJsDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED, !cli.isSwiftPackageAnalyzerDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED, !cli.isCocoapodsAnalyzerDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, !cli.isRubyGemspecDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !cli.isCentralDisabled());
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !cli.isNexusDisabled());
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, cli.getPathToBundleAudit());
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
if (cveBase12 != null && !cveBase12.isEmpty()) {
Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveBase12);
Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveBase20);
@@ -374,7 +456,7 @@ public class App {
encoder.setPattern("%d %C:%L%n%-5level - %msg%n");
encoder.setContext(context);
encoder.start();
final FileAppender fa = new FileAppender();
final FileAppender<ILoggingEvent> fa = new FileAppender<>();
fa.setAppend(true);
fa.setEncoder(encoder);
fa.setContext(context);
@@ -392,15 +474,16 @@ public class App {
}
/**
* Takes a path and resolves it to be a canonical & absolute path. The caveats are that this method will take an Ant style
* file selector path (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at least to the left of the first *
* or ?).
* Takes a path and resolves it to be a canonical &amp; absolute path. The
* caveats are that this method will take an Ant style file selector path
* (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at
* least to the left of the first * or ?).
*
* @param path the path to canonicalize
* @return the canonical path
*/
protected String ensureCanonicalPath(String path) {
String basePath = null;
String basePath;
String wildCards = null;
final String file = path.replace('\\', '/');
if (file.contains("*") || file.contains("?")) {

View File

@@ -22,7 +22,12 @@ package org.owasp.dependencycheck;
*
* @author Jeremy Long
*/
class InvalidScanPathException extends Exception {
public class InvalidScanPathException extends Exception {
/**
* The serial version UID for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new InvalidScanPathException.

View File

@@ -4,38 +4,47 @@ Command Line Arguments
The following table lists the command line arguments:
Short | Argument&nbsp;Name&nbsp;&nbsp; | Parameter | Description | Requirement
-------|-----------------------|-----------------|-------------|------------
\-a | \-\-app | \<name\> | The name of the application being scanned. This is a required argument. | 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
\-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](../suppression.html). | Optional
\-h | \-\-help | | Print the help message. | Optional
| \-\-advancedHelp | | Print the advanced help message. | Optional
\-v | \-\-version | | Print the version information. | 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
================
Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Parameter | Description | Default&nbsp;Value
-------|-----------------------|-----------------|----------------------------------------------------------------------------------|-------------------
| \-\-cveUrl12Modified | \<url\> | URL for the modified CVE 1.2 | http://nvd.nist.gov/download/nvdcve-modified.xml
| \-\-cveUrl20Modified | \<url\> | URL for the modified CVE 2.0 | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-modified.xml
| \-\-cveUrl12Base | \<url\> | Base URL for each year's CVE 1.2, the %d will be replaced with the year | http://nvd.nist.gov/download/nvdcve-%d.xml
| \-\-cveUrl20Base | \<url\> | Base URL for each year's CVE 2.0, the %d will be replaced with the year | http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
| \-\-cveUrl12Modified | \<url\> | URL for the modified CVE 1.2 | https://nvd.nist.gov/download/nvdcve-Modified.xml.gz
| \-\-cveUrl20Modified | \<url\> | URL for the modified CVE 2.0 | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-Modified.xml.gz
| \-\-cveUrl12Base | \<url\> | Base URL for each year's CVE 1.2, the %d will be replaced with the year | https://nvd.nist.gov/download/nvdcve-%d.xml.gz
| \-\-cveUrl20Base | \<url\> | Base URL for each year's CVE 2.0, the %d will be replaced with the year | https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
\-P | \-\-propertyfile | \<file\> | Specifies a file that contains properties to use instead of applicaion defaults. | &nbsp;
| \-\-updateonly | | If set only the update phase of dependency-check will be executed; no scan will be executed and no report will be generated. | &nbsp;
| \-\-disablePyDist | | Sets whether the Python Distribution Analyzer will be used. | false
| \-\-disablePyPkg | | Sets whether the Python Package Analyzer will be used. | false
| \-\-disableAutoconf | | Sets whether the Autoconf Analyzer will be used. | false
| \-\-disableOpenSSL | | Sets whether the OpenSSL Analyzer will be used. | false
| \-\-disableCmake | | Sets whether the Cmake Analyzer will be used. | false
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
| \-\-disablePyDist | | Sets whether the [experimental](../analyzers/index.html) Python Distribution Analyzer will be used. | false
| \-\-disablePyPkg | | Sets whether the [experimental](../analyzers/index.html) Python Package Analyzer will be used. | false
| \-\-disableNodeJS | | Sets whether the [experimental](../analyzers/index.html) Node.js Package Analyzer will be used. | false
| \-\-disableRubygems | | Sets whether the [experimental](../analyzers/index.html) Ruby Gemspec Analyzer will be used. | false
| \-\-disableBundleAudit | | Sets whether the [experimental](../analyzers/index.html) Ruby Bundler Audit Analyzer will be used. | false
| \-\-disableCocoapodsAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Cocoapods Analyzer will be used. | false
| \-\-disableSwiftPackageManagerAnalyzer | | Sets whether the [experimental](../analyzers/index.html) Swift Package Manager Analyzer will be used. | false
| \-\-disableAutoconf | | Sets whether the [experimental](../analyzers/index.html) Autoconf Analyzer will be used. | false
| \-\-disableOpenSSL | | Sets whether the OpenSSL Analyzer will be used. | false
| \-\-disableCmake | | Sets whether the [experimental](../analyzers/index.html) Cmake Analyzer will be disabled. | false
| \-\-disableArchive | | Sets whether the Archive Analyzer will be disabled. | false
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. | &nbsp;
| \-\-disableJar | | Sets whether the Jar Analyzer will be used. | false
| \-\-disableJar | | Sets whether the Jar Analyzer will be disabled. | false
| \-\-disableComposer | | Sets whether the [experimental](../analyzers/index.html) PHP Composer Lock File Analyzer will be disabled. | false
| \-\-disableCentral | | Sets whether the Central Analyzer will be used. **Disabling this analyzer is not recommended as it could lead to false negatives (e.g. libraries that have vulnerabilities may not be reported correctly).** If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer. | false
| \-\-disableNexus | | Sets whether the Nexus Analyzer will be used. Note, this has been superceded by the Central Analyzer. However, you can configure the Nexus URL to utilize an internally hosted Nexus Pro server. | false
| \-\-nexus | \<url\> | The url to the Nexus Server's web service end point (example: http://domain.enterprise/nexus/service/local/). If not set the Nexus Analyzer will be disabled. | &nbsp;
@@ -43,7 +52,8 @@ Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Paramete
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
| \-\-disableAssembly | | Sets whether or not the .NET Assembly Analyzer should be used. | false
| \-\-mono | \<path\> | The path to Mono for .NET Assembly analysis on non-windows systems. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources. | &nbsp;
| \-\-bundleAudit | | The path to the bundle-audit executable. | &nbsp;
| \-\-proxyserver | \<server\> | The proxy server to use when downloading resources; see the [proxy configuration](../data/proxy.html) page for more information. | &nbsp;
| \-\-proxyport | \<port\> | The proxy port to use when downloading resources. | &nbsp;
| \-\-connectiontimeout | \<timeout\> | The connection timeout (in milliseconds) to use when downloading resources. | &nbsp;
| \-\-proxypass | \<pass\> | The proxy password to use when downloading resources. | &nbsp;
@@ -54,3 +64,4 @@ Short | Argument&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Paramete
| \-\-dbPassword | \<password\> | The password for connecting to the database. | &nbsp;
| \-\-dbUser | \<user\> | The username used to connect to the database. | &nbsp;
\-d | \-\-data | \<path\> | The location of the data directory used to store persistent data. This option should generally not be set. | &nbsp;
| \-\-purge | | Delete the local copy of the NVD. This is used to force a refresh of the data. | &nbsp;

View File

@@ -9,19 +9,23 @@ Installation & Usage
====================
Download the dependency-check command line tool [here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-${project.version}-release.zip).
Extract the zip file to a location on your computer and put the 'bin' directory into the
path environment variable. On \*nix systems you will likely need to make the shell
script executable:
path environment variable.
$ chmod +777 dependency-check.sh
To scan a folder on the system you can run:
#set( $H = '#' )
$H$H$H Homebrew
$ brew install dependency-check
This puts an executable `dependency-check` script in the `/bin` directory of
your homebrew installation.
To scan a folder on the system you can run:
$H$H$H Windows
dependency-check.bat --app "My App Name" --scan "c:\java\application\lib"
dependency-check.bat --project "My App Name" --scan "c:\java\application\lib"
$H$H$H *nix
dependency-check.sh --app "My App Name" --scan "/java/application/lib"
dependency-check.sh --project "My App Name" --scan "/java/application/lib"
To view the command line arguments, see the <a href="arguments.html">arguments page</a>, or you can run:
@@ -29,4 +33,4 @@ $H$H$H Windows
dependency-check.bat --help
$H$H$H *nix
dependency-check.sh --help
dependency-check.sh --help

View File

@@ -1,26 +1,33 @@
/*
* Copyright 2015 OWASP.
* 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
* 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 The OWASP Foundatio. All Rights Reserved.
*/
package org.owasp.dependencycheck;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
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;
/**
*
@@ -28,25 +35,6 @@ import static org.junit.Assert.*;
*/
public class AppTest {
public AppTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of ensureCanonicalPath method, of class App.
*/
@@ -57,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

@@ -17,17 +17,14 @@
*/
package org.owasp.dependencycheck;
import org.owasp.dependencycheck.CliParser;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.commons.cli.ParseException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Settings;
@@ -48,14 +45,6 @@ public class CliParserTest {
Settings.cleanup(true);
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
/**
* Test of parse method, of class CliParser.
*
@@ -115,6 +104,63 @@ public class CliParserTest {
}
/**
* Test of parse method with failOnCVSS without an argument
*
* @throws Exception thrown when an exception occurs.
*/
@Test
public void testParse_failOnCVSSNoArg() throws Exception {
String[] args = {"--failOnCVSS"};
CliParser instance = new CliParser();
try {
instance.parse(args);
} catch (ParseException ex) {
Assert.assertTrue(ex.getMessage().contains("Missing argument"));
}
Assert.assertFalse(instance.isGetVersion());
Assert.assertFalse(instance.isGetHelp());
Assert.assertFalse(instance.isRunScan());
}
/**
* Test of parse method with failOnCVSS invalid argument. It should default to 11
*
* @throws Exception thrown when an exception occurs.
*/
@Test
public void testParse_failOnCVSSInvalidArgument() throws Exception {
String[] args = {"--failOnCVSS","bad"};
CliParser instance = new CliParser();
instance.parse(args);
Assert.assertEquals("Default should be 11", 11, instance.getFailOnCVSS());
Assert.assertFalse(instance.isGetVersion());
Assert.assertFalse(instance.isGetHelp());
Assert.assertFalse(instance.isRunScan());
}
/**
* Test of parse method with failOnCVSS invalid argument. It should default to 11
*
* @throws Exception thrown when an exception occurs.
*/
@Test
public void testParse_failOnCVSSValidArgument() throws Exception {
String[] args = {"--failOnCVSS","6"};
CliParser instance = new CliParser();
instance.parse(args);
Assert.assertEquals(6, instance.getFailOnCVSS());
Assert.assertFalse(instance.isGetVersion());
Assert.assertFalse(instance.isGetHelp());
Assert.assertFalse(instance.isRunScan());
}
/**
* Test of parse method with jar and cpe args, of class CliParser.
*
@@ -196,7 +242,7 @@ public class CliParserTest {
*/
@Test
public void testParse_scan_withFileExists() throws Exception {
File path = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").getPath());
File path = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath());
String[] args = {"-scan", path.getCanonicalPath(), "-out", "./", "-app", "test"};
CliParser instance = new CliParser();

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

@@ -17,7 +17,7 @@ Copyright & License
Dependency-Check is Copyright (c) 2012-2014 Jeremy Long. All Rights Reserved.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://github.com/jeremylong/DependencyCheck/dependency-check-cli/blob/master/LICENSE.txt) file for the full license.
Permission to modify and redistribute is granted under the terms of the Apache 2.0 license. See the [LICENSE.txt](https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/LICENSE.txt) file for the full license.
Dependency-Check makes use of several other open source libraries. Please see the [NOTICE.txt] [notices] file for more information.
@@ -25,4 +25,4 @@ Dependency-Check makes use of several other open source libraries. Please see th
[wiki]: https://github.com/jeremylong/DependencyCheck/wiki
[subscribe]: mailto:dependency-check+subscribe@googlegroups.com
[post]: mailto:dependency-check@googlegroups.com
[notices]: https://github.com/jeremylong/DependencyCheck/blob/master/NOTICES.txt
[notices]: https://raw.githubusercontent.com/jeremylong/DependencyCheck/master/NOTICE.txt

View File

@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.3.0</version>
<version>1.4.6-SNAPSHOT</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -83,9 +83,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</testResource>
<testResource>
<directory>${basedir}/src/test/resources</directory>
<excludes>
<exclude>**/mysql-connector-java-5.1.27-bin.jar</exclude>
</excludes>
<filtering>false</filtering>
</testResource>
</testResources>
@@ -110,183 +107,28 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
<configuration>
<includes>
<include>**/*.class</include>
</includes>
</configuration>
</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>
<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>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-Xlint:unchecked</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>${reporting.project-info-reports-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>summary</report>
<report>license</report>
<report>help</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${reporting.javadoc-plugin.version}</version>
<configuration>
<failOnError>false</failOnError>
<bottom>Copyright© 2012-15 Jeremy Long. All Rights Reserved.</bottom>
</configuration>
<reportSets>
<reportSet>
<id>default</id>
<reports>
<report>javadoc</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>${reporting.versions-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>dependency-updates-report</report>
<report>plugin-updates-report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>${reporting.jxr-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${reporting.cobertura-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${reporting.surefire-report-plugin.version}</version>
<reportSets>
<reportSet>
<reports>
<report>report-only</report>
</reports>
</reportSet>
<reportSet>
<id>integration-tests</id>
<reports>
@@ -296,30 +138,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>taglist-maven-plugin</artifactId>
<version>${reporting.taglist-plugin.version}</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>Todo Work</displayName>
<tags>
<tag>
<matchString>todo</matchString>
<matchType>ignoreCase</matchType>
</tag>
<tag>
<matchString>FIXME</matchString>
<matchType>exact</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -339,7 +157,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<version>${reporting.pmd-plugin.version}</version>
<configuration>
<targetJdk>1.6</targetJdk>
<linkXref>true</linkXref>
<linkXRef>true</linkXRef>
<sourceEncoding>utf-8</sourceEncoding>
<excludes>
<exclude>**/generated/*.java</exclude>
@@ -352,15 +170,14 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</rulesets>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>${reporting.findbugs-plugin.version}</version>
</plugin>
</plugins>
</reporting>
<dependencies>
<!-- Note, to stay compatible with Jenkins installations only JARs compiled to 1.6 can be used -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
@@ -371,22 +188,11 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- Set this to test so that each project that uses this has to have its own implementation of SLF4J -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<!-- For the CAL10N support -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-ext</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-utils</artifactId>
@@ -411,8 +217,8 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
@@ -433,16 +239,24 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<type>jar</type>
</dependency>
<dependency>
<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>
@@ -559,6 +373,21 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.0</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.8</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -570,23 +399,14 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<systemProperties>
<property>
<name>data.driver_path</name>
<value>${basedir}/${driver_path}</value>
<value>${driver_path}</value>
</property>
<property>
<name>data.driver_name</name>
@@ -598,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>
@@ -614,14 +434,68 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</build>
</profile>
<profile>
<!-- The following profile adds additional
dependencies that are only used during testing.
Additionally, these are only added when using "allTests" to
make the build slightly faster in most cases. -->
<id>Postgresql-IntegrationTest</id>
<activation>
<property>
<name>postgresql</name>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1204-jdbc42</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>data.driver_path</name>
<value>${driver_path}</value>
</property>
<property>
<name>data.driver_name</name>
<value>${driver_name}</value>
</property>
<property>
<name>data.connection_string</name>
<value>${connection_string}</value>
</property>
</systemProperties>
<includes>
<include>**/*MySqlIT.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!--
The following profile adds additional dependencies that are only
used during testing.
TODO move the following FP tests to a seperate invoker test in the
maven plugin project. Add checks against the XML to validate that
these do not report FP.
-->
<!--profile>
<id>False Positive Tests</id>
<activation>
<property>
<name>allTests</name>
<name>releaseTesting</name>
</property>
</activation>
<dependencies>
@@ -632,13 +506,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.2</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
@@ -709,20 +576,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.12.RELEASE</version>
<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>
@@ -773,6 +626,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<optional>true</optional>
</dependency>
</dependencies>
</profile>
</profile-->
</profiles>
</project>

View File

@@ -0,0 +1,129 @@
/*
* 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) 2016 Stefan Neuhaus. All Rights Reserved.
*/
package org.owasp.dependencycheck;
import org.owasp.dependencycheck.analyzer.Analyzer;
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.concurrent.Callable;
/**
* Task to support parallelism of dependency-check analysis. Analyses a single
* {@link Dependency} by a specific {@link Analyzer}.
*
* @author Stefan Neuhaus
*/
public class AnalysisTask implements Callable<Void> {
/**
* Instance of the logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisTask.class);
/**
* A reference to the analyzer.
*/
private final Analyzer analyzer;
/**
* The dependency to analyze.
*/
private final Dependency dependency;
/**
* A reference to the dependency-check engine.
*/
private final Engine engine;
/**
* The list of exceptions that may occur during analysis.
*/
private final List<Throwable> exceptions;
/**
* A reference to the global settings object.
*/
private final Settings settings;
/**
* Creates a new analysis task.
*
* @param analyzer a reference of the analyzer to execute
* @param dependency the dependency to analyze
* @param engine the dependency-check engine
* @param exceptions exceptions that occur during analysis will be added to
* this collection of exceptions
* @param settings a reference to the global settings object; this is
* necessary so that when the thread is started the dependencies have a
* correct reference to the global settings.
*/
AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions, Settings settings) {
this.analyzer = analyzer;
this.dependency = dependency;
this.engine = engine;
this.exceptions = exceptions;
this.settings = settings;
}
/**
* Executes the analysis task.
*
* @return null
*/
@Override
public Void call() {
try {
Settings.setInstance(settings);
if (shouldAnalyze()) {
LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
try {
analyzer.analyze(dependency, engine);
} catch (AnalysisException ex) {
LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
LOGGER.debug("", ex);
exceptions.add(ex);
} catch (Throwable ex) {
LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
LOGGER.debug("", ex);
exceptions.add(ex);
}
}
} finally {
Settings.cleanup(false);
}
return null;
}
/**
* Determines if the analyzer can analyze the given dependency.
*
* @return whether or not the analyzer can analyze the dependency
*/
protected boolean shouldAnalyze() {
if (analyzer instanceof FileTypeAnalyzer) {
final FileTypeAnalyzer fileTypeAnalyzer = (FileTypeAnalyzer) analyzer;
return fileTypeAnalyzer.accept(dependency.getActualFile());
}
return true;
}
}

View File

@@ -21,7 +21,6 @@ import org.owasp.dependencycheck.analyzer.AnalysisPhase;
import org.owasp.dependencycheck.analyzer.Analyzer;
import org.owasp.dependencycheck.analyzer.AnalyzerService;
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
@@ -29,6 +28,8 @@ import org.owasp.dependencycheck.data.update.CachedWebDataSource;
import org.owasp.dependencycheck.data.update.UpdateService;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.exception.NoDataException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
@@ -37,16 +38,31 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
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 used to process the files found by the scan, if a
* file is encountered and an Analyzer is associated with the file type then the file is turned into a dependency.
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
* used to process the files found by the scan, if a file is encountered and an
* Analyzer is associated with the file type then the file is turned into a
* dependency.
*
* @author Jeremy Long
*/
@@ -55,21 +71,26 @@ public class Engine implements FileFilter {
/**
* The list of dependencies.
*/
private List<Dependency> dependencies = new ArrayList<Dependency>();
private final List<Dependency> dependencies = Collections.synchronizedList(new ArrayList<Dependency>());
/**
* A Map of analyzers grouped by Analysis phase.
*/
private EnumMap<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<>(AnalysisPhase.class);
/**
* A Map of analyzers grouped by Analysis phase.
*/
private Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<>();
/**
* The ClassLoader to use when dynamically loading Analyzer and Update services.
* The ClassLoader to use when dynamically loading Analyzer and Update
* services.
*/
private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader();
/**
* A reference to the database.
*/
private CveDB database = null;
/**
* The Logger for use throughout the class.
*/
@@ -78,7 +99,8 @@ public class Engine implements FileFilter {
/**
* Creates a new Engine.
*
* @throws DatabaseException thrown if there is an error connecting to the database
* @throws DatabaseException thrown if there is an error connecting to the
* database
*/
public Engine() throws DatabaseException {
initializeEngine();
@@ -88,7 +110,8 @@ public class Engine implements FileFilter {
* Creates a new Engine.
*
* @param serviceClassLoader a reference the class loader being used
* @throws DatabaseException thrown if there is an error connecting to the database
* @throws DatabaseException thrown if there is an error connecting to the
* database
*/
public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
this.serviceClassLoader = serviceClassLoader;
@@ -96,9 +119,11 @@ public class Engine implements FileFilter {
}
/**
* Creates a new Engine using the specified classloader to dynamically load Analyzer and Update services.
* Creates a new Engine using the specified classloader to dynamically load
* Analyzer and Update services.
*
* @throws DatabaseException thrown if there is an error connecting to the database
* @throws DatabaseException thrown if there is an error connecting to the
* database
*/
protected final void initializeEngine() throws DatabaseException {
ConnectionFactory.initialize();
@@ -109,11 +134,16 @@ public class Engine implements FileFilter {
* Properly cleans up resources allocated during analysis.
*/
public void cleanup() {
if (database != null) {
database.close();
database = null;
}
ConnectionFactory.cleanup();
}
/**
* Loads the analyzers specified in the configuration file (or system properties).
* Loads the analyzers specified in the configuration file (or system
* properties).
*/
private void loadAnalyzers() {
if (!analyzers.isEmpty()) {
@@ -124,9 +154,8 @@ public class Engine implements FileFilter {
}
final AnalyzerService service = new AnalyzerService(serviceClassLoader);
final Iterator<Analyzer> iterator = service.getAnalyzers();
while (iterator.hasNext()) {
final Analyzer a = iterator.next();
final List<Analyzer> iterator = service.getAnalyzers();
for (Analyzer a : iterator) {
analyzers.get(a.getAnalysisPhase()).add(a);
if (a instanceof FileTypeAnalyzer) {
this.fileTypeAnalyzers.add((FileTypeAnalyzer) a);
@@ -145,11 +174,17 @@ public class Engine implements FileFilter {
}
/**
* Get the dependencies identified.
* Get the dependencies identified. The returned list is a reference to the
* engine's synchronized list. <b>You must synchronize on the returned
* list</b> when you modify and iterate over it from multiple threads. E.g.
* this holds for analyzers supporting parallel processing during their
* analysis phase.
*
* @return the dependencies identified
* @see Collections#synchronizedList(List)
* @see Analyzer#supportsParallelProcessing()
*/
public List<Dependency> getDependencies() {
public synchronized List<Dependency> getDependencies() {
return dependencies;
}
@@ -159,22 +194,40 @@ public class Engine implements FileFilter {
* @param dependencies the dependencies
*/
public void setDependencies(List<Dependency> dependencies) {
this.dependencies = dependencies;
synchronized (this.dependencies) {
this.dependencies.clear();
this.dependencies.addAll(dependencies);
}
}
/**
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
* Scans an array of files or directories. If a directory is specified, it
* will be scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param paths an array of paths to files or directories to be analyzed
* @return the list of dependencies scanned
* @since v0.3.2.5
*/
public List<Dependency> scan(String[] paths) {
final List<Dependency> deps = new ArrayList<Dependency>();
return scan(paths, null);
}
/**
* Scans an array of files or directories. If a directory is specified, it
* will be scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param paths an array of paths to files or directories to be analyzed
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of dependencies scanned
* @since v1.4.4
*/
public List<Dependency> scan(String[] paths, String projectReference) {
final List<Dependency> deps = new ArrayList<>();
for (String path : paths) {
final File file = new File(path);
final List<Dependency> d = scan(file);
final List<Dependency> d = scan(path, projectReference);
if (d != null) {
deps.addAll(d);
}
@@ -183,29 +236,61 @@ public class Engine implements FileFilter {
}
/**
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified
* are added to the dependency collection.
* Scans a given file or directory. If a directory is specified, it will be
* scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param path the path to a file or directory to be analyzed
* @return the list of dependencies scanned
*/
public List<Dependency> scan(String path) {
final File file = new File(path);
return scan(file);
return scan(path, null);
}
/**
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
* Scans a given file or directory. If a directory is specified, it will be
* scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param path the path to a file or directory to be analyzed
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of dependencies scanned
* @since v1.4.4
*/
public List<Dependency> scan(String path, String projectReference) {
final File file = new File(path);
return scan(file, projectReference);
}
/**
* Scans an array of files or directories. If a directory is specified, it
* will be scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param files an array of paths to files or directories to be analyzed.
* @return the list of dependencies
* @since v0.3.2.5
*/
public List<Dependency> scan(File[] files) {
final List<Dependency> deps = new ArrayList<Dependency>();
return scan(files, null);
}
/**
* Scans an array of files or directories. If a directory is specified, it
* will be scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param files an array of paths to files or directories to be analyzed.
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of dependencies
* @since v1.4.4
*/
public List<Dependency> scan(File[] files, String projectReference) {
final List<Dependency> deps = new ArrayList<>();
for (File file : files) {
final List<Dependency> d = scan(file);
final List<Dependency> d = scan(file, projectReference);
if (d != null) {
deps.addAll(d);
}
@@ -214,36 +299,33 @@ public class Engine implements FileFilter {
}
/**
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
* Scans a collection of files or directories. If a directory is specified,
* it will be scanned recursively. Any dependencies identified are added to
* the dependency collection.
*
* @param files a set of paths to files or directories to be analyzed
* @return the list of dependencies scanned
* @since v0.3.2.5
*/
public List<Dependency> scan(Set<File> files) {
final List<Dependency> deps = new ArrayList<Dependency>();
for (File file : files) {
final List<Dependency> d = scan(file);
if (d != null) {
deps.addAll(d);
}
}
return deps;
public List<Dependency> scan(Collection<File> files) {
return scan(files, null);
}
/**
* Scans a list of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
* identified are added to the dependency collection.
* Scans a collection of files or directories. If a directory is specified,
* it will be scanned recursively. Any dependencies identified are added to
* the dependency collection.
*
* @param files a set of paths to files or directories to be analyzed
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of dependencies scanned
* @since v0.3.2.5
* @since v1.4.4
*/
public List<Dependency> scan(List<File> files) {
final List<Dependency> deps = new ArrayList<Dependency>();
public List<Dependency> scan(Collection<File> files, String projectReference) {
final List<Dependency> deps = new ArrayList<>();
for (File file : files) {
final List<Dependency> d = scan(file);
final List<Dependency> d = scan(file, projectReference);
if (d != null) {
deps.addAll(d);
}
@@ -252,21 +334,37 @@ public class Engine implements FileFilter {
}
/**
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified
* are added to the dependency collection.
* Scans a given file or directory. If a directory is specified, it will be
* scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param file the path to a file or directory to be analyzed
* @return the list of dependencies scanned
* @since v0.3.2.4
*/
public List<Dependency> scan(File file) {
return scan(file, null);
}
/**
* Scans a given file or directory. If a directory is specified, it will be
* scanned recursively. Any dependencies identified are added to the
* dependency collection.
*
* @param file the path to a file or directory to be analyzed
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of dependencies scanned
* @since v1.4.4
*/
public List<Dependency> scan(File file, String projectReference) {
if (file.exists()) {
if (file.isDirectory()) {
return scanDirectory(file);
return scanDirectory(file, projectReference);
} else {
final Dependency d = scanFile(file);
final Dependency d = scanFile(file, projectReference);
if (d != null) {
final List<Dependency> deps = new ArrayList<Dependency>();
final List<Dependency> deps = new ArrayList<>();
deps.add(d);
return deps;
}
@@ -276,23 +374,38 @@ public class Engine implements FileFilter {
}
/**
* Recursively scans files and directories. Any dependencies identified are added to the dependency collection.
* Recursively scans files and directories. Any dependencies identified are
* added to the dependency collection.
*
* @param dir the directory to scan
* @return the list of Dependency objects scanned
*/
protected List<Dependency> scanDirectory(File dir) {
return scanDirectory(dir, null);
}
/**
* Recursively scans files and directories. Any dependencies identified are
* added to the dependency collection.
*
* @param dir the directory to scan
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the list of Dependency objects scanned
* @since v1.4.4
*/
protected List<Dependency> scanDirectory(File dir, String projectReference) {
final File[] files = dir.listFiles();
final List<Dependency> deps = new ArrayList<Dependency>();
final List<Dependency> deps = new ArrayList<>();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
final List<Dependency> d = scanDirectory(f);
final List<Dependency> d = scanDirectory(f, projectReference);
if (d != null) {
deps.addAll(d);
}
} else {
final Dependency d = scanFile(f);
final Dependency d = scanFile(f, projectReference);
deps.add(d);
}
}
@@ -301,91 +414,117 @@ public class Engine implements FileFilter {
}
/**
* Scans a specified file. If a dependency is identified it is added to the dependency collection.
* Scans a specified file. If a dependency is identified it is added to the
* dependency collection.
*
* @param file The file to scan
* @return the scanned dependency
*/
protected Dependency scanFile(File file) {
return scanFile(file, null);
}
/**
* Scans a specified file. If a dependency is identified it is added to the
* dependency collection.
*
* @param file The file to scan
* @param projectReference the name of the project or scope in which the
* dependency was identified
* @return the scanned dependency
* @since v1.4.4
*/
protected Dependency scanFile(File file, String projectReference) {
Dependency dependency = null;
if (file.isFile()) {
if (accept(file)) {
dependency = new Dependency(file);
dependencies.add(dependency);
if (projectReference != null) {
dependency.addProjectReference(projectReference);
}
final String sha1 = dependency.getSha1sum();
boolean found = false;
synchronized (dependencies) {
if (sha1 != null) {
for (Dependency existing : dependencies) {
if (sha1.equals(existing.getSha1sum())) {
found = true;
if (projectReference != null) {
existing.addProjectReference(projectReference);
}
if (existing.getActualFilePath() != null && dependency.getActualFilePath() != null
&& !existing.getActualFilePath().equals(dependency.getActualFilePath())) {
existing.addRelatedDependency(dependency);
} else {
dependency = existing;
}
break;
}
}
}
if (!found) {
dependencies.add(dependency);
}
}
} else {
LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file);
}
} else {
LOGGER.debug("Path passed to scanFile(File) is not a file: {}. Skipping the file.", file);
}
return dependency;
}
/**
* Runs the analyzers against all of the dependencies. Since the mutable dependencies list is exposed via
* {@link #getDependencies()}, this method iterates over a copy of the dependencies list. Thus, the potential for
* {@link java.util.ConcurrentModificationException}s is avoided, and analyzers may safely add or remove entries from the
* dependencies list.
* Runs the analyzers against all of the dependencies. Since the mutable
* dependencies list is exposed via {@link #getDependencies()}, this method
* iterates over a copy of the dependencies list. Thus, the potential for
* {@link java.util.ConcurrentModificationException}s is avoided, and
* analyzers may safely add or remove entries from the dependencies list.
* <p>
* Every effort is made to complete analysis on the dependencies. In some
* cases an exception will occur with part of the analysis being performed
* which may not affect the entire analysis. If an exception occurs it will
* be included in the thrown exception collection.
*
* @throws ExceptionCollection a collections of any exceptions that occurred
* during analysis
*/
public void analyzeDependencies() {
boolean autoUpdate = true;
try {
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
} catch (InvalidSettingException ex) {
LOGGER.debug("Invalid setting for auto-update; using true.");
}
if (autoUpdate) {
doUpdates();
}
public void analyzeDependencies() throws ExceptionCollection {
final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
initializeAndUpdateDatabase(exceptions);
//need to ensure that data exists
try {
ensureDataExists();
} catch (NoDataException ex) {
LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
LOGGER.debug("", ex);
return;
} catch (DatabaseException ex) {
LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
LOGGER.debug("", ex);
return;
throwFatalExceptionCollection("Unable to continue dependency-check analysis.", ex, exceptions);
}
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
LOGGER.info("Analysis Starting");
LOGGER.info("Analysis Started");
final long analysisStart = System.currentTimeMillis();
// analysis phases
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
for (Analyzer a : analyzerList) {
a = initializeAnalyzer(a);
for (final Analyzer analyzer : analyzerList) {
final long analyzerStart = System.currentTimeMillis();
try {
initializeAnalyzer(analyzer);
} catch (InitializationException ex) {
exceptions.add(ex);
continue;
}
/* need to create a copy of the collection because some of the
* analyzers may modify it. This prevents ConcurrentModificationExceptions.
* This is okay for adds/deletes because it happens per analyzer.
*/
LOGGER.debug("Begin Analyzer '{}'", a.getName());
final Set<Dependency> dependencySet = new HashSet<Dependency>();
dependencySet.addAll(dependencies);
for (Dependency d : dependencySet) {
boolean shouldAnalyze = true;
if (a instanceof FileTypeAnalyzer) {
final FileTypeAnalyzer fAnalyzer = (FileTypeAnalyzer) a;
shouldAnalyze = fAnalyzer.accept(d.getActualFile());
}
if (shouldAnalyze) {
LOGGER.debug("Begin Analysis of '{}'", d.getActualFilePath());
try {
a.analyze(d, this);
} catch (AnalysisException ex) {
LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath());
LOGGER.debug("", ex);
} catch (Throwable ex) {
//final AnalysisException ax = new AnalysisException(axMsg, ex);
LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath());
LOGGER.debug("", ex);
}
}
if (analyzer.isEnabled()) {
executeAnalysisTasks(analyzer, exceptions);
final long analyzerDurationMillis = System.currentTimeMillis() - analyzerStart;
final long analyzerDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(analyzerDurationMillis);
LOGGER.info("Finished {} ({} seconds)", analyzer.getName(), analyzerDurationSeconds);
} else {
LOGGER.debug("Skipping {} (not enabled)", analyzer.getName());
}
}
}
@@ -398,20 +537,134 @@ public class Engine implements FileFilter {
}
LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
LOGGER.info("Analysis Complete");
final long analysisDurationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - analysisStart);
LOGGER.info("Analysis Complete ({} seconds)", analysisDurationSeconds);
if (exceptions.size() > 0) {
throw new ExceptionCollection("One or more exceptions occurred during dependency-check analysis", exceptions);
}
}
/**
* Performs any necessary updates and initializes the database.
*
* @param exceptions a collection to store non-fatal exceptions
* @throws ExceptionCollection thrown if fatal exceptions occur
*/
private void initializeAndUpdateDatabase(final List<Throwable> exceptions) throws ExceptionCollection {
boolean autoUpdate = true;
try {
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
} catch (InvalidSettingException ex) {
LOGGER.debug("Invalid setting for auto-update; using true.");
exceptions.add(ex);
}
if (autoUpdate) {
try {
database = CveDB.getInstance();
doUpdates();
} catch (UpdateException ex) {
exceptions.add(ex);
LOGGER.warn("Unable to update Cached Web DataSource, using local "
+ "data instead. Results may not include recent vulnerabilities.");
LOGGER.debug("Update Error", ex);
} catch (DatabaseException ex) {
throw new ExceptionCollection("Unable to connect to the database", ex);
}
} else {
try {
if (ConnectionFactory.isH2Connection() && !ConnectionFactory.h2DataFileExists()) {
throw new ExceptionCollection(new NoDataException("Autoupdate is disabled and the database does not exist"), true);
} else {
database = CveDB.getInstance();
}
} catch (IOException ex) {
throw new ExceptionCollection(new DatabaseException("Autoupdate is disabled and unable to connect to the database"), true);
} catch (DatabaseException ex) {
throwFatalExceptionCollection("Unable to connect to the dependency-check database.", ex, exceptions);
}
}
}
/**
* Executes executes the analyzer using multiple threads.
*
* @param exceptions a collection of exceptions that occurred during
* analysis
* @param analyzer the analyzer to execute
* @throws ExceptionCollection thrown if exceptions occurred during analysis
*/
protected void executeAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) throws ExceptionCollection {
LOGGER.debug("Starting {}", analyzer.getName());
final List<AnalysisTask> analysisTasks = getAnalysisTasks(analyzer, exceptions);
final ExecutorService executorService = getExecutorService(analyzer);
try {
final List<Future<Void>> results = executorService.invokeAll(analysisTasks, 10, TimeUnit.MINUTES);
// ensure there was no exception during execution
for (Future<Void> result : results) {
try {
result.get();
} catch (ExecutionException e) {
throwFatalExceptionCollection("Analysis task failed with a fatal exception.", e, exceptions);
} catch (CancellationException e) {
throwFatalExceptionCollection("Analysis task timed out.", e, exceptions);
}
}
} catch (InterruptedException e) {
throwFatalExceptionCollection("Analysis has been interrupted.", e, exceptions);
} finally {
executorService.shutdown();
}
}
/**
* Returns the analysis tasks for the dependencies.
*
* @param analyzer the analyzer to create tasks for
* @param exceptions the collection of exceptions to collect
* @return a collection of analysis tasks
*/
protected List<AnalysisTask> getAnalysisTasks(Analyzer analyzer, List<Throwable> exceptions) {
final List<AnalysisTask> result = new ArrayList<>();
synchronized (dependencies) {
for (final Dependency dependency : dependencies) {
final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions, Settings.getInstance());
result.add(task);
}
}
return result;
}
/**
* Returns the executor service for a given analyzer.
*
* @param analyzer the analyzer to obtain an executor
* @return the executor service
*/
protected ExecutorService getExecutorService(Analyzer analyzer) {
if (analyzer.supportsParallelProcessing()) {
final int maximumNumberOfThreads = Runtime.getRuntime().availableProcessors();
LOGGER.debug("Parallel processing with up to {} threads: {}.", maximumNumberOfThreads, analyzer.getName());
return Executors.newFixedThreadPool(maximumNumberOfThreads);
} else {
LOGGER.debug("Parallel processing is not supported: {}.", analyzer.getName());
return Executors.newSingleThreadExecutor();
}
}
/**
* Initializes the given analyzer.
*
* @param analyzer the analyzer to initialize
* @return the initialized analyzer
* @throws InitializationException thrown when there is a problem
* initializing the analyzer
*/
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
protected void initializeAnalyzer(Analyzer analyzer) throws InitializationException {
try {
LOGGER.debug("Initializing {}", analyzer.getName());
analyzer.initialize();
} catch (Throwable ex) {
} catch (InitializationException ex) {
LOGGER.error("Exception occurred initializing {}.", analyzer.getName());
LOGGER.debug("", ex);
try {
@@ -419,8 +672,17 @@ public class Engine implements FileFilter {
} catch (Throwable ex1) {
LOGGER.trace("", ex1);
}
throw ex;
} catch (Throwable ex) {
LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName());
LOGGER.debug("", ex);
try {
analyzer.close();
} catch (Throwable ex1) {
LOGGER.trace("", ex1);
}
throw new InitializationException("Unexpected Exception", ex);
}
return analyzer;
}
/**
@@ -438,32 +700,31 @@ public class Engine implements FileFilter {
}
/**
* Cycles through the cached web data sources and calls update on all of them.
* Cycles through the cached web data sources and calls update on all of
* them.
*
* @throws UpdateException thrown if the operation fails
*/
public void doUpdates() {
public void doUpdates() throws UpdateException {
LOGGER.info("Checking for updates");
final long updateStart = System.currentTimeMillis();
final UpdateService service = new UpdateService(serviceClassLoader);
final Iterator<CachedWebDataSource> iterator = service.getDataSources();
while (iterator.hasNext()) {
final CachedWebDataSource source = iterator.next();
try {
source.update();
} catch (UpdateException ex) {
LOGGER.warn(
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
LOGGER.debug("Unable to update details for {}", source.getClass().getName(), ex);
}
source.update();
}
LOGGER.info("Check for updates complete");
LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart);
}
/**
* Returns a full list of all of the analyzers. This is useful for reporting which analyzers where used.
* Returns a full list of all of the analyzers. This is useful for reporting
* which analyzers where used.
*
* @return a list of Analyzers
*/
public List<Analyzer> getAnalyzers() {
final List<Analyzer> ret = new ArrayList<Analyzer>();
final List<Analyzer> ret = new ArrayList<>();
for (AnalysisPhase phase : AnalysisPhase.values()) {
final List<Analyzer> analyzerList = analyzers.get(phase);
ret.addAll(analyzerList);
@@ -475,8 +736,10 @@ public class Engine implements FileFilter {
* Checks all analyzers to see if an extension is supported.
*
* @param file a file extension
* @return true or false depending on whether or not the file extension is supported
* @return true or false depending on whether or not the file extension is
* supported
*/
@Override
public boolean accept(File file) {
if (file == null) {
return false;
@@ -500,22 +763,78 @@ public class Engine implements FileFilter {
}
/**
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
* Adds a file type analyzer. This has been added solely to assist in unit
* testing the Engine.
*
* @param fta the file type analyzer to add
*/
protected void addFileTypeAnalyzer(FileTypeAnalyzer fta) {
this.fileTypeAnalyzers.add(fta);
}
/**
* Checks the CPE Index to ensure documents exists. If none exist a
* NoDataException is thrown.
*
* @throws NoDataException thrown if no data exists in the CPE Index
* @throws DatabaseException thrown if there is an exception opening the database
*/
private void ensureDataExists() throws NoDataException, DatabaseException {
final CveDB cve = new CveDB();
try {
cve.open();
if (!cve.dataExists()) {
throw new NoDataException("No documents exist");
}
} catch (DatabaseException ex) {
throw new NoDataException(ex.getMessage(), ex);
} finally {
cve.close();
private void ensureDataExists() throws NoDataException {
if (database == null || !database.dataExists()) {
throw new NoDataException("No documents exist");
}
}
/**
* Constructs and throws a fatal exception collection.
*
* @param message the exception message
* @param throwable the cause
* @param exceptions a collection of exception to include
* @throws ExceptionCollection a collection of exceptions that occurred
* during analysis
*/
private void throwFatalExceptionCollection(String message, Throwable throwable, List<Throwable> exceptions) throws ExceptionCollection {
LOGGER.error("{}\n\n{}", throwable.getMessage(), message);
LOGGER.debug("", throwable);
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

@@ -27,6 +27,8 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.exception.ScanAgentException;
import org.owasp.dependencycheck.reporting.ReportGenerator;
import org.owasp.dependencycheck.utils.Settings;
@@ -34,14 +36,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class provides a way to easily conduct a scan solely based on existing evidence metadata rather than collecting evidence
* from the files themselves. This class is based on the Ant task and Maven plugin with the exception that it takes a list of
* dependencies that can be programmatically added from data in a spreadsheet, database or some other datasource and conduct a
* scan based on this pre-defined evidence.
* This class provides a way to easily conduct a scan solely based on existing
* evidence metadata rather than collecting evidence from the files themselves.
* This class is based on the Ant task and Maven plugin with the exception that
* it takes a list of dependencies that can be programmatically added from data
* in a spreadsheet, database or some other datasource and conduct a scan based
* on this pre-defined evidence.
*
* <h2>Example:</h2>
* <pre>
* List<Dependency> dependencies = new ArrayList<Dependency>();
* List&lt;Dependency&gt; dependencies = new ArrayList&lt;Dependency&gt;();
* Dependency dependency = new Dependency(new File(FileUtils.getBitBucket()));
* dependency.getProductEvidence().addEvidence("my-datasource", "name", "Jetty", Confidence.HIGH);
* dependency.getVersionEvidence().addEvidence("my-datasource", "version", "5.1.10", Confidence.HIGH);
@@ -55,11 +59,12 @@ import org.slf4j.LoggerFactory;
* scan.execute();
* </pre>
*
* @author Steve Springett <steve.springett@owasp.org>
* @author Steve Springett
*/
@SuppressWarnings("unused")
public class DependencyCheckScanAgent {
//<editor-fold defaultstate="collapsed" desc="private fields">
/**
* System specific new line character.
*/
@@ -72,6 +77,141 @@ public class DependencyCheckScanAgent {
* The application name for the report.
*/
private String applicationName = "Dependency-Check";
/**
* The pre-determined dependencies to scan
*/
private List<Dependency> dependencies;
/**
* The location of the data directory that contains
*/
private String dataDirectory = null;
/**
* Specifies the destination directory for the generated Dependency-Check
* report.
*/
private String reportOutputDirectory;
/**
* 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 and the CVSS score is set
* to 11. The valid range for the fail build on CVSS is 0 to 11, where
* anything above 10 will not cause the build to fail.
*/
private float failBuildOnCVSS = 11;
/**
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
* recommended that this be turned to false. Default is true.
*/
private boolean autoUpdate = true;
/**
* flag indicating whether or not to generate a report of findings.
*/
private boolean generateReport = true;
/**
* 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. Default is HTML.
*/
private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
/**
* The Proxy Server.
*/
private String proxyServer;
/**
* The Proxy Port.
*/
private String proxyPort;
/**
* The Proxy username.
*/
private String proxyUsername;
/**
* The Proxy password.
*/
private String proxyPassword;
/**
* The Connection Timeout.
*/
private String connectionTimeout;
/**
* The file path used for verbose logging.
*/
private String logFile = null;
/**
* flag indicating whether or not to show a summary of findings.
*/
private boolean showSummary = true;
/**
* The path to the suppression file.
*/
private String suppressionFile;
/**
* The password to use when connecting to the database.
*/
private String databasePassword;
/**
* Whether or not the Maven Central analyzer is enabled.
*/
private boolean centralAnalyzerEnabled = true;
/**
* The URL of Maven Central.
*/
private String centralUrl;
/**
* Whether or not the nexus analyzer is enabled.
*/
private boolean nexusAnalyzerEnabled = true;
/**
* The URL of the Nexus server.
*/
private String nexusUrl;
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
*/
private boolean nexusUsesProxy = true;
/**
* The database driver name; such as org.h2.Driver.
*/
private String databaseDriverName;
/**
* The path to the database driver JAR file if it is not on the class path.
*/
private String databaseDriverPath;
/**
* The database connection string.
*/
private String connectionString;
/**
* The user name for connecting to the database.
*/
private String databaseUser;
/**
* Additional ZIP File extensions to add analyze. This should be a
* comma-separated list of file extensions to treat like ZIP files.
*/
private String zipExtensions;
/**
* The url for the modified NVD CVE (1.2 schema).
*/
private String cveUrl12Modified;
/**
* The url for the modified NVD CVE (2.0 schema).
*/
private String cveUrl20Modified;
/**
* Base Data Mirror URL for CVE 1.2.
*/
private String cveUrl12Base;
/**
* Data Mirror URL for CVE 2.0.
*/
private String cveUrl20Base;
/**
* The path to Mono for .NET assembly analysis on non-windows systems.
*/
private String pathToMono;
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="getters/setters">
/**
* Get the value of applicationName.
@@ -91,11 +231,6 @@ public class DependencyCheckScanAgent {
this.applicationName = applicationName;
}
/**
* The pre-determined dependencies to scan
*/
private List<Dependency> dependencies;
/**
* Returns a list of pre-determined dependencies.
*
@@ -114,11 +249,6 @@ public class DependencyCheckScanAgent {
this.dependencies = dependencies;
}
/**
* The location of the data directory that contains
*/
private String dataDirectory = null;
/**
* Get the value of dataDirectory.
*
@@ -137,11 +267,6 @@ public class DependencyCheckScanAgent {
this.dataDirectory = dataDirectory;
}
/**
* Specifies the destination directory for the generated Dependency-Check report.
*/
private String reportOutputDirectory;
/**
* Get the value of reportOutputDirectory.
*
@@ -160,13 +285,6 @@ public class DependencyCheckScanAgent {
this.reportOutputDirectory = reportOutputDirectory;
}
/**
* 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 and the CVSS score is set to 11. The valid range
* for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
*/
private float failBuildOnCVSS = 11;
/**
* Get the value of failBuildOnCVSS.
*
@@ -185,12 +303,6 @@ public class DependencyCheckScanAgent {
this.failBuildOnCVSS = failBuildOnCVSS;
}
/**
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default
* is true.
*/
private boolean autoUpdate = true;
/**
* Get the value of autoUpdate.
*
@@ -209,11 +321,6 @@ public class DependencyCheckScanAgent {
this.autoUpdate = autoUpdate;
}
/**
* flag indicating whether or not to generate a report of findings.
*/
private boolean generateReport = true;
/**
* Get the value of generateReport.
*
@@ -232,12 +339,6 @@ public class DependencyCheckScanAgent {
this.generateReport = generateReport;
}
/**
* 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. Default is HTML.
*/
private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
/**
* Get the value of reportFormat.
*
@@ -256,11 +357,6 @@ public class DependencyCheckScanAgent {
this.reportFormat = reportFormat;
}
/**
* The Proxy Server.
*/
private String proxyServer;
/**
* Get the value of proxyServer.
*
@@ -283,7 +379,9 @@ public class DependencyCheckScanAgent {
* Get the value of proxyServer.
*
* @return the value of proxyServer
* @deprecated use {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()} instead
* @deprecated use
* {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()}
* instead
*/
@Deprecated
public String getProxyUrl() {
@@ -302,11 +400,6 @@ public class DependencyCheckScanAgent {
this.proxyServer = proxyUrl;
}
/**
* The Proxy Port.
*/
private String proxyPort;
/**
* Get the value of proxyPort.
*
@@ -325,11 +418,6 @@ public class DependencyCheckScanAgent {
this.proxyPort = proxyPort;
}
/**
* The Proxy username.
*/
private String proxyUsername;
/**
* Get the value of proxyUsername.
*
@@ -348,11 +436,6 @@ public class DependencyCheckScanAgent {
this.proxyUsername = proxyUsername;
}
/**
* The Proxy password.
*/
private String proxyPassword;
/**
* Get the value of proxyPassword.
*
@@ -371,11 +454,6 @@ public class DependencyCheckScanAgent {
this.proxyPassword = proxyPassword;
}
/**
* The Connection Timeout.
*/
private String connectionTimeout;
/**
* Get the value of connectionTimeout.
*
@@ -394,11 +472,6 @@ public class DependencyCheckScanAgent {
this.connectionTimeout = connectionTimeout;
}
/**
* The file path used for verbose logging.
*/
private String logFile = null;
/**
* Get the value of logFile.
*
@@ -417,11 +490,6 @@ public class DependencyCheckScanAgent {
this.logFile = logFile;
}
/**
* The path to the suppression file.
*/
private String suppressionFile;
/**
* Get the value of suppressionFile.
*
@@ -440,11 +508,6 @@ public class DependencyCheckScanAgent {
this.suppressionFile = suppressionFile;
}
/**
* flag indicating whether or not to show a summary of findings.
*/
private boolean showSummary = true;
/**
* Get the value of showSummary.
*
@@ -463,11 +526,6 @@ public class DependencyCheckScanAgent {
this.showSummary = showSummary;
}
/**
* Whether or not the Maven Central analyzer is enabled.
*/
private boolean centralAnalyzerEnabled = true;
/**
* Get the value of centralAnalyzerEnabled.
*
@@ -486,11 +544,6 @@ public class DependencyCheckScanAgent {
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
}
/**
* The URL of Maven Central.
*/
private String centralUrl;
/**
* Get the value of centralUrl.
*
@@ -509,11 +562,6 @@ public class DependencyCheckScanAgent {
this.centralUrl = centralUrl;
}
/**
* Whether or not the nexus analyzer is enabled.
*/
private boolean nexusAnalyzerEnabled = true;
/**
* Get the value of nexusAnalyzerEnabled.
*
@@ -532,11 +580,6 @@ public class DependencyCheckScanAgent {
this.nexusAnalyzerEnabled = nexusAnalyzerEnabled;
}
/**
* The URL of the Nexus server.
*/
private String nexusUrl;
/**
* Get the value of nexusUrl.
*
@@ -555,11 +598,6 @@ public class DependencyCheckScanAgent {
this.nexusUrl = nexusUrl;
}
/**
* Whether or not the defined proxy should be used when connecting to Nexus.
*/
private boolean nexusUsesProxy = true;
/**
* Get the value of nexusUsesProxy.
*
@@ -578,11 +616,6 @@ public class DependencyCheckScanAgent {
this.nexusUsesProxy = nexusUsesProxy;
}
/**
* The database driver name; such as org.h2.Driver.
*/
private String databaseDriverName;
/**
* Get the value of databaseDriverName.
*
@@ -601,11 +634,6 @@ public class DependencyCheckScanAgent {
this.databaseDriverName = databaseDriverName;
}
/**
* The path to the database driver JAR file if it is not on the class path.
*/
private String databaseDriverPath;
/**
* Get the value of databaseDriverPath.
*
@@ -624,11 +652,6 @@ public class DependencyCheckScanAgent {
this.databaseDriverPath = databaseDriverPath;
}
/**
* The database connection string.
*/
private String connectionString;
/**
* Get the value of connectionString.
*
@@ -647,11 +670,6 @@ public class DependencyCheckScanAgent {
this.connectionString = connectionString;
}
/**
* The user name for connecting to the database.
*/
private String databaseUser;
/**
* Get the value of databaseUser.
*
@@ -670,11 +688,6 @@ public class DependencyCheckScanAgent {
this.databaseUser = databaseUser;
}
/**
* The password to use when connecting to the database.
*/
private String databasePassword;
/**
* Get the value of databasePassword.
*
@@ -693,12 +706,6 @@ public class DependencyCheckScanAgent {
this.databasePassword = databasePassword;
}
/**
* Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat like ZIP
* files.
*/
private String zipExtensions;
/**
* Get the value of zipExtensions.
*
@@ -717,11 +724,6 @@ public class DependencyCheckScanAgent {
this.zipExtensions = zipExtensions;
}
/**
* The url for the modified NVD CVE (1.2 schema).
*/
private String cveUrl12Modified;
/**
* Get the value of cveUrl12Modified.
*
@@ -740,11 +742,6 @@ public class DependencyCheckScanAgent {
this.cveUrl12Modified = cveUrl12Modified;
}
/**
* The url for the modified NVD CVE (2.0 schema).
*/
private String cveUrl20Modified;
/**
* Get the value of cveUrl20Modified.
*
@@ -763,11 +760,6 @@ public class DependencyCheckScanAgent {
this.cveUrl20Modified = cveUrl20Modified;
}
/**
* Base Data Mirror URL for CVE 1.2.
*/
private String cveUrl12Base;
/**
* Get the value of cveUrl12Base.
*
@@ -786,11 +778,6 @@ public class DependencyCheckScanAgent {
this.cveUrl12Base = cveUrl12Base;
}
/**
* Data Mirror URL for CVE 2.0.
*/
private String cveUrl20Base;
/**
* Get the value of cveUrl20Base.
*
@@ -809,11 +796,6 @@ public class DependencyCheckScanAgent {
this.cveUrl20Base = cveUrl20Base;
}
/**
* The path to Mono for .NET assembly analysis on non-windows systems.
*/
private String pathToMono;
/**
* Get the value of pathToMono.
*
@@ -831,17 +813,23 @@ public class DependencyCheckScanAgent {
public void setPathToMono(String pathToMono) {
this.pathToMono = pathToMono;
}
//</editor-fold>
/**
* Executes the Dependency-Check on the dependent libraries.
*
* @return the Engine used to scan the dependencies.
* @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if there is an exception connecting to the database
* @throws ExceptionCollection a collection of one or more exceptions that
* occurred during analysis.
*/
private Engine executeDependencyCheck() throws DatabaseException {
private Engine executeDependencyCheck() throws ExceptionCollection {
populateSettings();
Engine engine = null;
engine = new Engine();
final Engine engine;
try {
engine = new Engine();
} catch (DatabaseException ex) {
throw new ExceptionCollection(ex, true);
}
engine.setDependencies(this.dependencies);
engine.analyzeDependencies();
return engine;
@@ -852,38 +840,22 @@ 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;
CveDB cve = null;
private void generateExternalReports(Engine engine, File outDirectory) throws ScanAgentException {
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
LOGGER.debug("Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
}
}
final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
try {
r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
} catch (IOException ex) {
LOGGER.error(
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
LOGGER.debug("", ex);
} catch (Throwable 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);
}
}
/**
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
* required to change the proxy server, port, and connection timeout.
* Takes the properties supplied and updates the dependency-check settings.
* Additionally, this sets the system properties required to change the
* proxy server, port, and connection timeout.
*/
private void populateSettings() {
Settings.initialize();
@@ -898,74 +870,36 @@ public class DependencyCheckScanAgent {
}
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
if (proxyServer != null && !proxyServer.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
}
if (proxyPort != null && !proxyPort.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
}
if (proxyUsername != null && !proxyUsername.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUsername);
}
if (proxyPassword != null && !proxyPassword.isEmpty()) {
Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
}
if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
}
if (suppressionFile != null && !suppressionFile.isEmpty()) {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
}
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_SERVER, proxyServer);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PORT, proxyPort);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_USERNAME, proxyUsername);
Settings.setStringIfNotEmpty(Settings.KEYS.PROXY_PASSWORD, proxyPassword);
Settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
Settings.setStringIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
if (centralUrl != null && !centralUrl.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl);
}
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_CENTRAL_URL, centralUrl);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
if (nexusUrl != null && !nexusUrl.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
}
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
}
if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
}
if (connectionString != null && !connectionString.isEmpty()) {
Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
}
if (databaseUser != null && !databaseUser.isEmpty()) {
Settings.setString(Settings.KEYS.DB_USER, databaseUser);
}
if (databasePassword != null && !databasePassword.isEmpty()) {
Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
}
if (zipExtensions != null && !zipExtensions.isEmpty()) {
Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
}
if (cveUrl12Modified != null && !cveUrl12Modified.isEmpty()) {
Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
}
if (cveUrl20Modified != null && !cveUrl20Modified.isEmpty()) {
Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
}
if (cveUrl12Base != null && !cveUrl12Base.isEmpty()) {
Settings.setString(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
}
if (cveUrl20Base != null && !cveUrl20Base.isEmpty()) {
Settings.setString(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
}
if (pathToMono != null && !pathToMono.isEmpty()) {
Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
}
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
Settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
Settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_12_URL, cveUrl12Modified);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_MODIFIED_20_URL, cveUrl20Modified);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_1_2, cveUrl12Base);
Settings.setStringIfNotEmpty(Settings.KEYS.CVE_SCHEMA_2_0, cveUrl20Base);
Settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
}
/**
* Executes the dependency-check and generates the report.
*
* @return a reference to the engine used to perform the scan.
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
* there is an exception executing the scan.
*/
public Engine execute() throws ScanAgentException {
Engine engine = null;
@@ -980,10 +914,12 @@ public class DependencyCheckScanAgent {
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
}
} catch (DatabaseException ex) {
LOGGER.error(
"Unable to connect to the dependency-check database; analysis has stopped");
LOGGER.debug("", ex);
} catch (ExceptionCollection ex) {
if (ex.isFatal()) {
LOGGER.error("A fatal exception occurred during analysis; analysis has stopped. Please see the debug log for more details.");
LOGGER.debug("", ex);
}
throw new ScanAgentException("One or more exceptions occurred during analysis; please see the debug log for more details.", ex);
} finally {
Settings.cleanup(true);
if (engine != null) {
@@ -994,11 +930,12 @@ public class DependencyCheckScanAgent {
}
/**
* Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
* configuration.
* Checks to see if a vulnerability has been identified with a CVSS score
* that is above the threshold set in the configuration.
*
* @param dependencies the list of dependency objects
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
* there is an exception executing the scan.
*/
private void checkForFailure(List<Dependency> dependencies) throws ScanAgentException {
final StringBuilder ids = new StringBuilder();
@@ -1018,7 +955,7 @@ public class DependencyCheckScanAgent {
}
if (ids.length() > 0) {
final String msg = String.format("%n%nDependency-Check Failure:%n"
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater than '%.1f': %s%n"
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
throw new ScanAgentException(msg);
@@ -1026,7 +963,8 @@ public class DependencyCheckScanAgent {
}
/**
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
* Generates a warning message listing a summary of dependencies and their
* associated CPE and CVE entries.
*
* @param dependencies a list of dependency objects
*/
@@ -1063,5 +1001,4 @@ public class DependencyCheckScanAgent {
summary.toString());
}
}
}

View File

@@ -17,20 +17,125 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base class for analyzers to avoid code duplication of initialize and close as
* most analyzers do not need these methods.
*
* @author Jeremy Long
*/
public abstract class AbstractAnalyzer implements Analyzer {
/**
* The initialize method does nothing for this Analyzer.
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAnalyzer.class);
/**
* A flag indicating whether or not the analyzer is enabled.
*/
private volatile boolean enabled = true;
/**
* Get the value of enabled.
*
* @return the value of enabled
*/
@Override
public boolean isEnabled() {
return enabled;
}
/**
* Set the value of enabled.
*
* @param enabled new value of enabled
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
protected abstract String getAnalyzerEnabledSettingKey();
/**
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
protected abstract void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException;
/**
* Initializes a given Analyzer. This will be skipped if the analyzer is
* disabled.
*
* @throws InitializationException thrown if there is an exception
*/
protected void initializeAnalyzer() throws InitializationException {
}
/**
* Closes a given Analyzer. This will be skipped if the analyzer is
* disabled.
*
* @throws Exception thrown if there is an exception
*/
protected void closeAnalyzer() throws Exception {
// Intentionally empty, analyzer will override this if they must close a resource.
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
@Override
public void initialize() throws Exception {
//do nothing
public final void analyze(Dependency dependency, Engine engine) throws AnalysisException {
if (this.isEnabled()) {
analyzeDependency(dependency, engine);
}
}
/**
* The initialize method does nothing for this Analyzer.
*
* @throws InitializationException thrown if there is an exception
*/
@Override
public final void initialize() throws InitializationException {
final String key = getAnalyzerEnabledSettingKey();
try {
this.setEnabled(Settings.getBoolean(key, true));
} catch (InvalidSettingException ex) {
LOGGER.warn("Invalid setting for property '{}'", key);
LOGGER.debug("", ex);
}
if (isEnabled()) {
initializeAnalyzer();
} else {
LOGGER.debug("{} has been disabled", getName());
}
}
/**
@@ -39,7 +144,19 @@ public abstract class AbstractAnalyzer implements Analyzer {
* @throws Exception thrown if there is an exception
*/
@Override
public void close() throws Exception {
//do nothing
public final void close() throws Exception {
if (isEnabled()) {
closeAnalyzer();
}
}
/**
* The default is to support parallel processing.
*
* @return true
*/
@Override
public boolean supportsParallelProcessing() {
return true;
}
}

View File

@@ -17,11 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,24 +25,17 @@ import java.io.FileFilter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* The base FileTypeAnalyzer that all analyzers that have specific file types they analyze should extend.
* The base FileTypeAnalyzer that all analyzers that have specific file types
* they analyze should extend.
*
* @author Jeremy Long
*/
public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implements FileTypeAnalyzer {
//<editor-fold defaultstate="collapsed" desc="Constructor">
/**
* Base constructor that all children must call. This checks the configuration to determine if the analyzer is enabled.
*/
public AbstractFileTypeAnalyzer() {
reset();
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Field definitions">
//<editor-fold defaultstate="collapsed" desc="Field definitions, getters, and setters ">
/**
* The logger.
*/
@@ -58,7 +46,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
private boolean filesMatched = false;
/**
* Get the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
* Get the value of filesMatched. A flag indicating whether the scan
* included any file types this analyzer supports.
*
* @return the value of filesMatched
*/
@@ -67,7 +56,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
}
/**
* Set the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
* Set the value of filesMatched. A flag indicating whether the scan
* included any file types this analyzer supports.
*
* @param filesMatched new value of filesMatched
*/
@@ -75,122 +65,62 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
this.filesMatched = filesMatched;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Final implementations for the Analyzer interface">
/**
* A flag indicating whether or not the analyzer is enabled.
*/
private boolean enabled = true;
/**
* Get the value of enabled.
* Initializes the analyzer.
*
* @return the value of enabled
* @throws InitializationException thrown if there is an exception during
* initialization
*/
public boolean isEnabled() {
return enabled;
@Override
protected final void initializeAnalyzer() throws InitializationException {
if (filesMatched) {
initializeFileTypeAnalyzer();
} else {
this.setEnabled(false);
}
}
/**
* Set the value of enabled.
*
* @param enabled new value of enabled
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
//</editor-fold>
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Abstract methods children must implement">
/**
* <p>
* Returns the {@link java.io.FileFilter} used to determine which files are to be analyzed. An example would be an analyzer
* that inspected Java jar files. Implementors may use {@link org.owasp.dependencycheck.utils.FileFilterBuilder}.</p>
* Returns the {@link java.io.FileFilter} used to determine which files are
* to be analyzed. An example would be an analyzer that inspected Java jar
* files. Implementors may use
* {@link org.owasp.dependencycheck.utils.FileFilterBuilder}.</p>
* <p>
* If the analyzer returns null it will not cause additional files to be
* analyzed, but will be executed against every file loaded.</p>
*
* @return the file filter used to determine which files are to be analyzed
* <p/>
* <p>
* If the analyzer returns null it will not cause additional files to be analyzed, but will be executed against every file
* loaded.</p>
*/
protected abstract FileFilter getFileFilter();
/**
* Initializes the file type analyzer.
*
* @throws Exception thrown if there is an exception during initialization
* @throws InitializationException thrown if there is an exception during
* initialization
*/
protected abstract void initializeFileTypeAnalyzer() throws Exception;
protected abstract void initializeFileTypeAnalyzer() throws InitializationException;
//</editor-fold>
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
* Determines if the file can be analyzed by the analyzer.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
* @param pathname the path to the file
* @return true if the file can be analyzed by the given analyzer; otherwise
* false
*/
protected abstract void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException;
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
protected abstract String getAnalyzerEnabledSettingKey();
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Final implementations for the Analyzer interface">
/**
* Initializes the analyzer.
*
* @throws Exception thrown if there is an exception during initialization
*/
@Override
public final void initialize() throws Exception {
if (filesMatched) {
initializeFileTypeAnalyzer();
} else {
enabled = false;
}
}
/**
* Resets the enabled flag on the analyzer.
*/
@Override
public final void reset() {
final String key = getAnalyzerEnabledSettingKey();
try {
enabled = Settings.getBoolean(key, true);
} catch (InvalidSettingException ex) {
LOGGER.warn("Invalid setting for property '{}'", key);
LOGGER.debug("", ex);
LOGGER.warn("{} has been disabled", getName());
}
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
@Override
public final void analyze(Dependency dependency, Engine engine) throws AnalysisException {
if (enabled) {
analyzeFileType(dependency, engine);
}
}
@Override
public boolean accept(File pathname) {
final FileFilter filter = getFileFilter();
boolean accepted = false;
if (null == filter) {
LOGGER.error("The '{}' analyzer is misconfigured and does not have a file filter; it will be disabled", getName());
} else if (enabled) {
} else if (this.isEnabled()) {
accepted = filter.accept(pathname);
if (accepted) {
filesMatched = true;
@@ -199,13 +129,10 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
return accepted;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Static utility methods">
/**
* <p>
* Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a final static
* declaration.</p>
* <p/>
* Utility method to help in the creation of the extensions set. This
* constructs a new Set that can be used in a final static declaration.</p>
* <p>
* This implementation was copied from
* http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction</p>
@@ -214,10 +141,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
* @return a Set of strings.
*/
protected static Set<String> newHashSet(String... strings) {
final Set<String> set = new HashSet<String>();
final Set<String> set = new HashSet<>(strings.length);
Collections.addAll(set, strings);
return set;
}
//</editor-fold>
}

View File

@@ -25,18 +25,21 @@ import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionParser;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.xml.suppression.SuppressionParseException;
import org.owasp.dependencycheck.xml.suppression.SuppressionParser;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* Abstract base suppression analyzer that contains methods for parsing the suppression xml file.
* Abstract base suppression analyzer that contains methods for parsing the
* suppression xml file.
*
* @author Jeremy Long
*/
@@ -61,12 +64,15 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
/**
* The initialize method loads the suppression XML file.
*
* @throws Exception thrown if there is an exception
* @throws InitializationException thrown if there is an exception
*/
@Override
public void initialize() throws Exception {
super.initialize();
loadSuppressionData();
public void initializeAnalyzer() throws InitializationException {
try {
loadSuppressionData();
} catch (SuppressionParseException ex) {
throw new InitializationException("Error initializing the suppression analyzer", ex);
}
}
/**
@@ -101,9 +107,10 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
final SuppressionParser parser = new SuppressionParser();
File file = null;
try {
rules = parser.parseSuppressionRules(this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml"));
} catch (SuppressionParseException ex) {
LOGGER.debug("Unable to parse the base suppression data file", ex);
final InputStream in = this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml");
rules = parser.parseSuppressionRules(in);
} catch (SAXException ex) {
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
}
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
@@ -123,29 +130,33 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
}
} else {
file = new File(suppressionFilePath);
if (!file.exists()) {
final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
if (suppressionsFromClasspath != null) {
deleteTempFile = true;
file = FileUtils.getTempFile("suppression", "xml");
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
} catch (IOException ex) {
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
try (InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath)) {
if (suppressionsFromClasspath != null) {
deleteTempFile = true;
file = FileUtils.getTempFile("suppression", "xml");
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
} catch (IOException ex) {
throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
}
}
}
}
}
if (file != null) {
if (!file.exists()) {
final String msg = String.format("Suppression file '%s' does not exists", file.getPath());
LOGGER.warn(msg);
throw new SuppressionParseException(msg);
}
try {
//rules = parser.parseSuppressionRules(file);
rules.addAll(parser.parseSuppressionRules(file));
LOGGER.debug("{} suppression rules were loaded.", rules.size());
} catch (SuppressionParseException ex) {
LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
LOGGER.warn(ex.getMessage());
LOGGER.debug("", ex);
throw ex;
}
}
@@ -153,6 +164,8 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
} catch (MalformedURLException ex) {
throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
} catch (SuppressionParseException ex) {
throw ex;
} catch (IOException ex) {
throwSuppressionParseException("Unable to create temp file for suppressions", ex);
} finally {
@@ -167,7 +180,8 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
*
* @param message the exception message
* @param exception the cause of the exception
* @throws SuppressionParseException throws the generated SuppressionParseException
* @throws SuppressionParseException throws the generated
* SuppressionParseException
*/
private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
LOGGER.warn(message);

View File

@@ -28,10 +28,18 @@ public enum AnalysisPhase {
* Initialization phase.
*/
INITIAL,
/**
* Pre information collection phase.
*/
PRE_INFORMATION_COLLECTION,
/**
* Information collection phase.
*/
INFORMATION_COLLECTION,
/**
* Post information collection phase.
*/
POST_INFORMATION_COLLECTION,
/**
* Pre identifier analysis phase.
*/

View File

@@ -20,24 +20,28 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* An interface that defines an Analyzer that is used to identify Dependencies. An analyzer will collect information
* about the dependency in the form of Evidence.
* An interface that defines an Analyzer that is used to identify Dependencies.
* An analyzer will collect information about the dependency in the form of
* Evidence.
*
* @author Jeremy Long
*/
public interface Analyzer {
/**
* Analyzes the given dependency. The analysis could be anything from identifying an Identifier for the dependency,
* to finding vulnerabilities, etc. Additionally, if the analyzer collects enough information to add a description
* or license information for the dependency it should be added.
* Analyzes the given dependency. The analysis could be anything from
* identifying an Identifier for the dependency, to finding vulnerabilities,
* etc. Additionally, if the analyzer collects enough information to add a
* description or license information for the dependency it should be added.
*
* @param dependency a dependency to analyze.
* @param engine the engine that is scanning the dependencies - this is useful if we need to check other
* dependencies
* @throws AnalysisException is thrown if there is an error analyzing the dependency file
* @param engine the engine that is scanning the dependencies - this is
* useful if we need to check other dependencies
* @throws AnalysisException is thrown if there is an error analyzing the
* dependency file
*/
void analyze(Dependency dependency, Engine engine) throws AnalysisException;
@@ -56,16 +60,33 @@ public interface Analyzer {
AnalysisPhase getAnalysisPhase();
/**
* The initialize method is called (once) prior to the analyze method being called on all of the dependencies.
* The initialize method is called (once) prior to the analyze method being
* called on all of the dependencies.
*
* @throws Exception is thrown if an exception occurs initializing the analyzer.
* @throws InitializationException is thrown if an exception occurs
* initializing the analyzer.
*/
void initialize() throws Exception;
void initialize() throws InitializationException;
/**
* The close method is called after all of the dependencies have been analyzed.
* The close method is called after all of the dependencies have been
* analyzed.
*
* @throws Exception is thrown if an exception occurs closing the analyzer.
*/
void close() throws Exception;
/**
* Returns whether multiple instances of the same type of analyzer can run in parallel.
* Note that running analyzers of different types in parallel is not supported at all.
*
* @return {@code true} if the analyzer supports parallel processing, {@code false} else
*/
boolean supportsParallelProcessing();
/**
* Get the value of enabled.
*
* @return the value of enabled
*/
boolean isEnabled();
}

View File

@@ -17,8 +17,13 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.LoggerFactory;
/**
* The Analyzer Service Loader. This class loads all services that implement
@@ -27,11 +32,15 @@ import java.util.ServiceLoader;
* @author Jeremy Long
*/
public class AnalyzerService {
/**
* The Logger for use throughout the class.
*/
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AnalyzerService.class);
/**
* The service loader for analyzers.
*/
private final ServiceLoader<Analyzer> loader;
private final ServiceLoader<Analyzer> service;
/**
* Creates a new instance of AnalyzerService.
@@ -39,15 +48,31 @@ public class AnalyzerService {
* @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services
*/
public AnalyzerService(ClassLoader classLoader) {
loader = ServiceLoader.load(Analyzer.class, classLoader);
service = ServiceLoader.load(Analyzer.class, classLoader);
}
/**
* Returns an Iterator for all instances of the Analyzer interface.
* Returns a list of all instances of the Analyzer interface.
*
* @return an iterator of Analyzers.
* @return a list of Analyzers.
*/
public Iterator<Analyzer> getAnalyzers() {
return loader.iterator();
public List<Analyzer> getAnalyzers() {
final List<Analyzer> analyzers = new ArrayList<>();
final Iterator<Analyzer> iterator = service.iterator();
boolean experimentalEnabled = false;
try {
experimentalEnabled = Settings.getBoolean(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, false);
} catch (InvalidSettingException ex) {
LOGGER.error("invalid experimental setting", ex);
}
while (iterator.hasNext()) {
final Analyzer a = iterator.next();
if (!experimentalEnabled && a.getClass().isAnnotationPresent(Experimental.class)) {
continue;
}
LOGGER.debug("Loaded Analyzer {}", a.getName());
analyzers.add(a);
}
return analyzers;
}
}

View File

@@ -18,18 +18,14 @@
package org.owasp.dependencycheck.analyzer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -40,22 +36,28 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.compressors.CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2Utils;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipUtils;
import org.apache.commons.compress.utils.IOUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* An analyzer that extracts files from archives and ensures any supported files contained within the archive are added to the
* dependency list.</p>
* An analyzer that extracts files from archives and ensures any supported files
* contained within the archive are added to the dependency list.</p>
*
* @author Jeremy Long
*/
@@ -66,11 +68,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class);
/**
* The buffer size to use when extracting files from the archive.
*/
private static final int BUFFER_SIZE = 4096;
/**
* The count of directories created during analysis. This is used for creating temporary directories.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static int dirCount = 0;
/**
@@ -78,7 +77,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private File tempFileLocation = null;
/**
* The max scan depth that the analyzer will recursively extract nested archives.
* The max scan depth that the analyzer will recursively extract nested
* archives.
*/
private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
/**
@@ -98,42 +98,45 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The set of things we can handle with Zip methods
*/
private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
private static final Set<String> KNOWN_ZIP_EXT = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
/**
* The set of file extensions supported by this analyzer. Note for developers, any additions to this list will need to be
* explicitly handled in extractFiles().
* The set of file extensions supported by this analyzer. Note for
* developers, any additions to this list will need to be explicitly handled
* in {@link #extractFiles(File, File, Engine)}.
*/
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
/**
* Detects files with extensions to remove from the engine's collection of dependencies.
*/
private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz").build();
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2");
static {
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
if (additionalZipExt != null) {
final Set<String> ext = new HashSet<String>(Arrays.asList(additionalZipExt));
ZIPPABLES.addAll(ext);
final String[] ext = additionalZipExt.split("\\s*,\\s*");
Collections.addAll(KNOWN_ZIP_EXT, ext);
}
EXTENSIONS.addAll(ZIPPABLES);
EXTENSIONS.addAll(KNOWN_ZIP_EXT);
}
/**
* Detects files with extensions to remove from the engine's collection of
* dependencies.
*/
private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance()
.addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2").build();
/**
* The file filter used to filter supported files.
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
@Override
protected FileFilter getFileFilter() {
return FILTER;
}
/**
* Detects files with .zip extension.
*/
private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build();
@Override
protected FileFilter getFileFilter() {
return FILTER;
}
/**
* Returns the name of the analyzer.
*
@@ -156,7 +159,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -168,118 +172,184 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The initialize method does nothing for this Analyzer.
*
* @throws Exception is thrown if there is an exception deleting or creating temporary files
* @throws InitializationException is thrown if there is an exception
* deleting or creating temporary files
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
setEnabled(false);
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
setEnabled(false);
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}
/**
* The close method deletes any temporary files and directories created during analysis.
* The close method deletes any temporary files and directories created
* during analysis.
*
* @throws Exception thrown if there is an exception deleting temporary files
* @throws Exception thrown if there is an exception deleting temporary
* files
*/
@Override
public void close() throws Exception {
public void closeAnalyzer() throws Exception {
if (tempFileLocation != null && tempFileLocation.exists()) {
LOGGER.debug("Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success && tempFileLocation != null && tempFileLocation.exists() && tempFileLocation.list().length > 0) {
LOGGER.warn("Failed to delete some temporary files, see the log for more details");
if (!success && tempFileLocation.exists()) {
final String[] l = tempFileLocation.list();
if (l != null && l.length > 0) {
LOGGER.warn("Failed to delete some temporary files, see the log for more details");
}
}
}
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
* Does not support parallel processing as it both modifies and iterates
* over the engine's list of dependencies.
*
* @return <code>true</code> if the analyzer supports parallel processing;
* otherwise <code>false</code>
* @see #analyzeDependency(Dependency, Engine)
* @see #findMoreDependencies(Engine, File)
*/
@Override
public boolean supportsParallelProcessing() {
return false;
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException thrown if there is an analysis exception
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
final File f = new File(dependency.getActualFilePath());
final File tmpDir = getNextTempDirectory();
extractFiles(f, tmpDir, engine);
//make a copy
List<Dependency> dependencies = new ArrayList<Dependency>(engine.getDependencies());
engine.scan(tmpDir);
List<Dependency> newDependencies = engine.getDependencies();
if (dependencies.size() != newDependencies.size()) {
//get the new dependencies
final Set<Dependency> dependencySet = new HashSet<Dependency>();
dependencySet.addAll(newDependencies);
dependencySet.removeAll(dependencies);
final List<Dependency> dependencySet = findMoreDependencies(engine, tmpDir);
if (dependencySet != null && !dependencySet.isEmpty()) {
for (Dependency d : dependencySet) {
//fix the dependency's display name and path
final String displayPath = String.format("%s%s",
dependency.getFilePath(),
d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
final String displayName = String.format("%s: %s",
dependency.getFileName(),
d.getFileName());
d.setFilePath(displayPath);
d.setFileName(displayName);
if (d.getFilePath().startsWith(tmpDir.getAbsolutePath())) {
//fix the dependency's display name and path
final String displayPath = String.format("%s%s",
dependency.getFilePath(),
d.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
final String displayName = String.format("%s: %s",
dependency.getFileName(),
d.getFileName());
d.setFilePath(displayPath);
d.setFileName(displayName);
d.setProjectReferences(dependency.getProjectReferences());
//TODO - can we get more evidence from the parent? EAR contains module name, etc.
//analyze the dependency (i.e. extract files) if it is a supported type.
if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) {
scanDepth += 1;
analyze(d, engine);
scanDepth -= 1;
//TODO - can we get more evidence from the parent? EAR contains module name, etc.
//analyze the dependency (i.e. extract files) if it is a supported type.
if (this.accept(d.getActualFile()) && scanDepth < MAX_SCAN_DEPTH) {
scanDepth += 1;
analyze(d, engine);
scanDepth -= 1;
}
} else {
for (Dependency sub : dependencySet) {
if (sub.getFilePath().startsWith(tmpDir.getAbsolutePath())) {
final String displayPath = String.format("%s%s",
dependency.getFilePath(),
sub.getActualFilePath().substring(tmpDir.getAbsolutePath().length()));
final String displayName = String.format("%s: %s",
dependency.getFileName(),
sub.getFileName());
sub.setFilePath(displayPath);
sub.setFileName(displayName);
}
}
}
}
}
if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) {
if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) {
final File tdir = getNextTempDirectory();
final String fileName = dependency.getFileName();
LOGGER.info(String.format("The zip file '%s' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName));
final File tmpLoc = new File(tdir, fileName.substring(0, fileName.length() - 3) + "jar");
try {
org.apache.commons.io.FileUtils.copyFile(tdir, tmpLoc);
dependencies = new ArrayList<Dependency>(engine.getDependencies());
engine.scan(tmpLoc);
newDependencies = engine.getDependencies();
if (dependencies.size() != newDependencies.size()) {
//get the new dependencies
final Set<Dependency> dependencySet = new HashSet<Dependency>();
dependencySet.addAll(newDependencies);
dependencySet.removeAll(dependencies);
if (dependencySet.size() != 1) {
LOGGER.info("Deep copy of ZIP to JAR file resulted in more then one dependency?");
}
for (Dependency d : dependencySet) {
//fix the dependency's display name and path
d.setFilePath(dependency.getFilePath());
d.setDisplayFileName(dependency.getFileName());
}
}
} catch (IOException ex) {
LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex);
}
}
addDisguisedJarsToDependencies(dependency, engine);
engine.getDependencies().remove(dependency);
}
Collections.sort(engine.getDependencies());
}
/**
* If a zip file was identified as a possible JAR, this method will add the
* zip to the list of dependencies.
*
* @param dependency the zip file
* @param engine the engine
* @throws AnalysisException thrown if there is an issue
*/
private void addDisguisedJarsToDependencies(Dependency dependency, Engine engine) throws AnalysisException {
if (ZIP_FILTER.accept(dependency.getActualFile()) && isZipFileActuallyJarFile(dependency)) {
final File tempDir = getNextTempDirectory();
final String fileName = dependency.getFileName();
LOGGER.info("The zip file '{}' appears to be a JAR file, making a copy and analyzing it as a JAR.", fileName);
final File tmpLoc = new File(tempDir, fileName.substring(0, fileName.length() - 3) + "jar");
//store the archives sha1 and change it so that the engine doesn't think the zip and jar file are the same
// and add it is a related dependency.
final String archiveSha1 = dependency.getSha1sum();
try {
dependency.setSha1sum("");
org.apache.commons.io.FileUtils.copyFile(dependency.getActualFile(), tmpLoc);
final List<Dependency> dependencySet = findMoreDependencies(engine, tmpLoc);
if (dependencySet != null && !dependencySet.isEmpty()) {
for (Dependency d : dependencySet) {
//fix the dependency's display name and path
if (d.getActualFile().equals(tmpLoc)) {
d.setFilePath(dependency.getFilePath());
d.setDisplayFileName(dependency.getFileName());
} else {
for (Dependency sub : d.getRelatedDependencies()) {
if (sub.getActualFile().equals(tmpLoc)) {
sub.setFilePath(dependency.getFilePath());
sub.setDisplayFileName(dependency.getFileName());
}
}
}
}
}
} catch (IOException ex) {
LOGGER.debug("Unable to perform deep copy on '{}'", dependency.getActualFile().getPath(), ex);
} finally {
dependency.setSha1sum(archiveSha1);
}
}
}
/**
* Scan the given file/folder, and return any new dependencies found.
*
* @param engine used to scan
* @param file target of scanning
* @return any dependencies that weren't known to the engine before
*/
private static List<Dependency> findMoreDependencies(Engine engine, File file) {
return engine.scan(file);
}
/**
* Retrieves the next temporary directory to extract an archive too.
*
@@ -309,41 +379,119 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException thrown if the archive is not found
*/
private void extractFiles(File archive, File destination, Engine engine) throws AnalysisException {
if (archive == null || destination == null) {
return;
}
FileInputStream fis = null;
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
throw new AnalysisException("Archive file was not found.", ex);
}
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
try {
if (ZIPPABLES.contains(archiveExt)) {
extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("tar".equals(archiveExt)) {
extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
final File f = new File(destination, uncompressedName);
if (engine.accept(f)) {
decompressFile(new GzipCompressorInputStream(new BufferedInputStream(fis)), f);
}
if (archive != null && destination != null) {
String archiveExt = FileUtils.getFileExtension(archive.getName());
if (archiveExt == null) {
return;
}
} catch (ArchiveExtractionException ex) {
LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
LOGGER.debug("", ex);
} catch (IOException ex) {
LOGGER.warn("Exception reading archive '{}'.", archive.getName());
LOGGER.debug("", ex);
} finally {
archiveExt = archiveExt.toLowerCase();
final FileInputStream fis;
try {
fis.close();
} catch (IOException ex) {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
throw new AnalysisException("Archive file was not found.", ex);
}
BufferedInputStream in = null;
ZipArchiveInputStream zin = null;
TarArchiveInputStream tin = null;
GzipCompressorInputStream gin = null;
BZip2CompressorInputStream bzin = null;
try {
if (KNOWN_ZIP_EXT.contains(archiveExt)) {
in = new BufferedInputStream(fis);
ensureReadableJar(archiveExt, in);
zin = new ZipArchiveInputStream(in);
extractArchive(zin, destination, engine);
} else if ("tar".equals(archiveExt)) {
in = new BufferedInputStream(fis);
tin = new TarArchiveInputStream(in);
extractArchive(tin, destination, engine);
} else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
final String uncompressedName = GzipUtils.getUncompressedFilename(archive.getName());
final File f = new File(destination, uncompressedName);
if (engine.accept(f)) {
in = new BufferedInputStream(fis);
gin = new GzipCompressorInputStream(in);
decompressFile(gin, f);
}
} else if ("bz2".equals(archiveExt) || "tbz2".equals(archiveExt)) {
final String uncompressedName = BZip2Utils.getUncompressedFilename(archive.getName());
final File f = new File(destination, uncompressedName);
if (engine.accept(f)) {
in = new BufferedInputStream(fis);
bzin = new BZip2CompressorInputStream(in);
decompressFile(bzin, f);
}
}
} catch (ArchiveExtractionException ex) {
LOGGER.warn("Exception extracting archive '{}'.", archive.getName());
LOGGER.debug("", ex);
} catch (IOException ex) {
LOGGER.warn("Exception reading archive '{}'.", archive.getName());
LOGGER.debug("", ex);
} finally {
//overly verbose and not needed... but keeping it anyway due to
//having issue with file handles being left open
FileUtils.close(fis);
FileUtils.close(in);
FileUtils.close(zin);
FileUtils.close(tin);
FileUtils.close(gin);
FileUtils.close(bzin);
}
}
}
/**
* Checks if the file being scanned is a JAR that begins with '#!/bin' which
* indicates it is a fully executable jar. If a fully executable JAR is
* identified the input stream will be advanced to the start of the actual
* JAR file ( skipping the script).
*
* @see
* <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing
* Spring Boot Applications</a>
* @param archiveExt the file extension
* @param in the input stream
* @throws IOException thrown if there is an error reading the stream
*/
private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
if ("jar".equals(archiveExt) && in.markSupported()) {
in.mark(7);
final byte[] b = new byte[7];
final int read = in.read(b);
if (read == 7
&& b[0] == '#'
&& b[1] == '!'
&& b[2] == '/'
&& b[3] == 'b'
&& b[4] == 'i'
&& b[5] == 'n'
&& b[6] == '/') {
boolean stillLooking = true;
int chr;
int nxtChr;
while (stillLooking && (chr = in.read()) != -1) {
if (chr == '\n' || chr == '\r') {
in.mark(4);
if ((chr = in.read()) != -1) {
if (chr == 'P' && (chr = in.read()) != -1) {
if (chr == 'K' && (chr = in.read()) != -1) {
if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) {
if (nxtChr == chr + 1) {
stillLooking = false;
in.reset();
}
}
}
}
}
}
}
} else {
in.reset();
}
}
}
@@ -354,81 +502,54 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
* @param input the archive to extract files from
* @param destination the location to write the files too
* @param engine the dependency-check engine
* @throws ArchiveExtractionException thrown if there is an exception extracting files from the archive
* @throws ArchiveExtractionException thrown if there is an exception
* extracting files from the archive
*/
private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
ArchiveEntry entry;
try {
while ((entry = input.getNextEntry()) != null) {
final File file = new File(destination, entry.getName());
if (entry.isDirectory()) {
final File d = new File(destination, entry.getName());
if (!d.exists()) {
if (!d.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", d.getAbsolutePath());
throw new AnalysisException(msg);
}
}
} else {
final File file = new File(destination, entry.getName());
if (engine.accept(file)) {
LOGGER.debug("Extracting '{}'", file.getPath());
BufferedOutputStream bos = null;
FileOutputStream fos = null;
try {
final File parent = file.getParentFile();
if (!parent.isDirectory()) {
if (!parent.mkdirs()) {
final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
throw new AnalysisException(msg);
}
}
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);
int count;
final byte[] data = new byte[BUFFER_SIZE];
while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
bos.write(data, 0, count);
}
bos.flush();
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
} catch (IOException ex) {
LOGGER.debug("", ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
}
if (!file.exists() && !file.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", file.getAbsolutePath());
throw new AnalysisException(msg);
}
} else if (engine.accept(file)) {
extractAcceptedFile(input, file);
}
}
} catch (IOException ex) {
throw new ArchiveExtractionException(ex);
} catch (Throwable ex) {
} catch (IOException | AnalysisException ex) {
throw new ArchiveExtractionException(ex);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
FileUtils.close(input);
}
}
/**
* Extracts a file from an archive.
*
* @param input the archives input stream
* @param file the file to extract
* @throws AnalysisException thrown if there is an error
*/
private static void extractAcceptedFile(ArchiveInputStream input, File file) throws AnalysisException {
LOGGER.debug("Extracting '{}'", file.getPath());
final File parent = file.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
final String msg = String.format("Unable to build directory '%s'.", parent.getAbsolutePath());
throw new AnalysisException(msg);
}
try (FileOutputStream fos = new FileOutputStream(file)) {
IOUtils.copy(input, fos);
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
final String msg = String.format("Unable to find file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
} catch (IOException ex) {
LOGGER.debug("", ex);
final String msg = String.format("IO Exception while parsing file '%s'.", file.getName());
throw new AnalysisException(msg, ex);
}
}
@@ -437,32 +558,16 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param inputStream the compressed file
* @param outputFile the location to write the decompressed file
* @throws ArchiveExtractionException thrown if there is an exception decompressing the file
* @throws ArchiveExtractionException thrown if there is an exception
* decompressing the file
*/
private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
LOGGER.debug("Decompressing '{}'", outputFile.getPath());
FileOutputStream out = null;
try {
out = new FileOutputStream(outputFile);
final byte[] buffer = new byte[BUFFER_SIZE];
int n = 0;
while (-1 != (n = inputStream.read(buffer))) {
out.write(buffer, 0, n);
}
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
throw new ArchiveExtractionException(ex);
try (FileOutputStream out = new FileOutputStream(outputFile)) {
IOUtils.copy(inputStream, out);
} catch (IOException ex) {
LOGGER.debug("", ex);
throw new ArchiveExtractionException(ex);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
}
}
@@ -496,7 +601,6 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
} finally {
ZipFile.closeQuietly(zip);
}
return isJar;
}
}

View File

@@ -17,15 +17,13 @@
*/
package org.owasp.dependencycheck.analyzer;
import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
@@ -39,16 +37,19 @@ import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.xml.parsers.ParserConfigurationException;
import org.owasp.dependencycheck.exception.InitializationException;
import org.apache.commons.lang3.SystemUtils;
import org.owasp.dependencycheck.utils.XmlUtils;
/**
* Analyzer for getting company, product, and version information from a .NET assembly.
* Analyzer for getting company, product, and version information from a .NET
* assembly.
*
* @author colezlaw
*
@@ -71,14 +72,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
* The temp value for GrokAssembly.exe
*/
private File grokAssemblyExe = null;
/**
* The DocumentBuilder for parsing the XML
*/
private DocumentBuilder builder;
/**
* Message Conveyer
*/
private static final IMessageConveyor MESSAGE_CONVERYOR = new MessageConveyor(Locale.getDefault());
/**
* Logger
*/
@@ -89,18 +82,19 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
*
* @return the list of arguments to begin populating the ProcessBuilder
*/
private List<String> buildArgumentList() {
protected List<String> buildArgumentList() {
// Use file.separator as a wild guess as to whether this is Windows
final List<String> args = new ArrayList<String>();
if (!"\\".equals(System.getProperty("file.separator"))) {
final List<String> args = new ArrayList<>();
if (!SystemUtils.IS_OS_WINDOWS) {
if (Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH) != null) {
args.add(Settings.getString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH));
} else {
} else if (isInPath("mono")) {
args.add("mono");
} else {
return null;
}
}
args.add(grokAssemblyExe.getPath());
return args;
}
@@ -112,7 +106,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException if anything goes sideways
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine)
public void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
if (grokAssemblyExe == null) {
LOGGER.warn("GrokAssembly didn't get deployed");
@@ -120,23 +114,26 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
}
final List<String> args = buildArgumentList();
if (args == null) {
LOGGER.warn("Assembly Analyzer was unable to execute");
return;
}
args.add(dependency.getActualFilePath());
final ProcessBuilder pb = new ProcessBuilder(args);
BufferedReader rdr = null;
Document doc = null;
try {
final Process proc = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(proc.getErrorStream(), "UTF-8"));
String line = null;
// CHECKSTYLE:OFF
while (rdr.ready() && (line = rdr.readLine()) != null) {
LOGGER.warn("Error from GrokAssembly: {}", line);
}
// CHECKSTYLE:ON
int rc = 0;
final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
doc = builder.parse(proc.getInputStream());
// Try evacuating the error stream
final String errorStream = IOUtils.toString(proc.getErrorStream(), "UTF-8");
if (null != errorStream && !errorStream.isEmpty()) {
LOGGER.warn("Error from GrokAssembly: {}", errorStream);
}
int rc = 0;
try {
rc = proc.waitFor();
} catch (InterruptedException ie) {
@@ -147,14 +144,16 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getActualFilePath());
return;
} else if (rc != 0) {
LOGGER.warn("Return code {} from GrokAssembly", rc);
LOGGER.debug("Return code {} from GrokAssembly; dependency-check is unable to analyze the library: {}",
rc, dependency.getActualFilePath());
return;
}
final XPath xpath = XPathFactory.newInstance().newXPath();
// First, see if there was an error
final String error = xpath.evaluate("/assembly/error", doc);
if (error != null && !"".equals(error)) {
if (error != null && !error.isEmpty()) {
throw new AnalysisException(error);
}
@@ -176,110 +175,99 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
product, Confidence.HIGH));
}
} catch (IOException ioe) {
} catch (ParserConfigurationException pce) {
throw new AnalysisException("Error initializing the assembly analyzer", pce);
} catch (IOException | XPathExpressionException ioe) {
throw new AnalysisException(ioe);
} catch (SAXException saxe) {
throw new AnalysisException("Couldn't parse GrokAssembly result", saxe);
} catch (XPathExpressionException xpe) {
// This shouldn't happen
throw new AnalysisException(xpe);
} finally {
if (rdr != null) {
try {
rdr.close();
} catch (IOException ex) {
LOGGER.debug("ignore", ex);
}
}
LOGGER.error("----------------------------------------------------");
LOGGER.error("Failed to read the Assembly Analyzer results. "
+ "On some systems mono-runtime and mono-devel need to be installed.");
LOGGER.error("----------------------------------------------------");
throw new AnalysisException("Couldn't parse Assembly Analyzer results (GrokAssembly)", saxe);
}
// This shouldn't happen
}
/**
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a temporary location.
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a
* temporary location.
*
* @throws Exception if anything goes wrong
* @throws InitializationException thrown if anything goes wrong
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
FileOutputStream fos = null;
InputStream is = null;
public void initializeFileTypeAnalyzer() throws InitializationException {
final File tempFile;
final String cfg;
try {
fos = new FileOutputStream(tempFile);
is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
final byte[] buff = new byte[4096];
int bread = -1;
while ((bread = is.read(buff)) >= 0) {
fos.write(buff, 0, bread);
}
tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
cfg = tempFile.getPath() + ".config";
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create temporary file for the assembly analyzer", ex);
}
try (FileOutputStream fos = new FileOutputStream(tempFile);
InputStream is = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe");
FileOutputStream fosCfg = new FileOutputStream(cfg);
InputStream isCfg = AssemblyAnalyzer.class.getClassLoader().getResourceAsStream("GrokAssembly.exe.config")) {
IOUtils.copy(is, fos);
grokAssemblyExe = tempFile;
// Set the temp file to get deleted when we're done
grokAssemblyExe.deleteOnExit();
LOGGER.debug("Extracted GrokAssembly.exe to {}", grokAssemblyExe.getPath());
IOUtils.copy(isCfg, fosCfg);
LOGGER.debug("Extracted GrokAssembly.exe.config to {}", cfg);
} catch (IOException ioe) {
this.setEnabled(false);
LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
throw new AnalysisException("Could not extract GrokAssembly.exe", ioe);
} finally {
if (fos != null) {
try {
fos.close();
} catch (Throwable e) {
LOGGER.debug("Error closing output stream");
}
}
if (is != null) {
try {
is.close();
} catch (Throwable e) {
LOGGER.debug("Error closing input stream");
}
}
throw new InitializationException("Could not extract GrokAssembly.exe", ioe);
}
// Now, need to see if GrokAssembly actually runs from this location.
final List<String> args = buildArgumentList();
BufferedReader rdr = null;
//TODO this creates an "unreported" error - if someone doesn't look
// at the command output this could easily be missed (especially in an
// Ant or Maven build.
//
// We need to create a non-fatal warning error type that will
// get added to the report.
//TODO this idea needs to get replicated to the bundle audit analyzer.
if (args == null) {
setEnabled(false);
LOGGER.error("----------------------------------------------------");
LOGGER.error(".NET Assembly Analyzer could not be initialized and at least one "
+ "'exe' or 'dll' was scanned. The 'mono' executable could not be found on "
+ "the path; either disable the Assembly Analyzer or configure the path mono. "
+ "On some systems mono-runtime and mono-devel need to be installed.");
LOGGER.error("----------------------------------------------------");
return;
}
try {
final ProcessBuilder pb = new ProcessBuilder(args);
final Process p = pb.start();
// Try evacuating the error stream
rdr = new BufferedReader(new InputStreamReader(p.getErrorStream(), "UTF-8"));
// CHECKSTYLE:OFF
while (rdr.ready() && rdr.readLine() != null) {
// We expect this to complain
}
// CHECKSTYLE:ON
final Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(p.getInputStream());
IOUtils.copy(p.getErrorStream(), NullOutputStream.NULL_OUTPUT_STREAM);
final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
final Document doc = builder.parse(p.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String error = xpath.evaluate("/assembly/error", doc);
if (p.waitFor() != 1 || error == null || "".equals(error)) {
if (p.waitFor() != 1 || error == null || error.isEmpty()) {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
LOGGER.debug("GrokAssembly.exe is not working properly");
grokAssemblyExe = null;
this.setEnabled(false);
throw new AnalysisException("Could not execute .NET AssemblyAnalyzer");
}
} catch (Throwable e) {
if (e instanceof AnalysisException) {
throw (AnalysisException) e;
} else {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
this.setEnabled(false);
throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
}
} finally {
if (rdr != null) {
try {
rdr.close();
} catch (IOException ex) {
LOGGER.trace("ignore", ex);
}
setEnabled(false);
throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
}
} catch (InitializationException e) {
setEnabled(false);
throw e;
} catch (IOException | ParserConfigurationException | SAXException | XPathExpressionException | InterruptedException e) {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
setEnabled(false);
throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
}
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
/**
@@ -288,14 +276,15 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
* @throws Exception thrown if there is a problem closing the analyzer
*/
@Override
public void close() throws Exception {
super.close();
public void closeAnalyzer() throws Exception {
try {
if (grokAssemblyExe != null && !grokAssemblyExe.delete()) {
LOGGER.debug("Unable to delete temporary GrokAssembly.exe; attempting delete on exit");
grokAssemblyExe.deleteOnExit();
}
} catch (SecurityException se) {
LOGGER.debug("Can't delete temporary GrokAssembly.exe");
grokAssemblyExe.deleteOnExit();
}
}
@@ -331,7 +320,8 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -339,4 +329,27 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED;
}
/**
* Tests to see if a file is in the system path. <b>Note</b> - the current
* implementation only works on non-windows platforms. For purposes of the
* AssemblyAnalyzer this is okay as this is only needed on Mac/*nix.
*
* @param file the executable to look for
* @return <code>true</code> if the file exists; otherwise
* <code>false</code>
*/
private boolean isInPath(String file) {
final ProcessBuilder pb = new ProcessBuilder("which", file);
try {
final Process proc = pb.start();
final int retCode = proc.waitFor();
if (retCode == 0) {
return true;
}
} catch (IOException | InterruptedException ex) {
LOGGER.debug("Path search failed for " + file, ex);
}
return false;
}
}

View File

@@ -30,18 +30,21 @@ import org.owasp.dependencycheck.utils.UrlStringUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Autoconf input files named configure.ac or configure.in. Files simply named "configure" are also analyzed,
* assuming they are generated by Autoconf, and contain certain special package descriptor variables.
* Used to analyze Autoconf input files named configure.ac or configure.in.
* Files simply named "configure" are also analyzed, assuming they are generated
* by Autoconf, and contain certain special package descriptor variables.
*
* @author Dale Visser <dvisser@ida.org>
* @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project - Free Software Foundation (FSF)</a>
* @author Dale Visser
* @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project
* - Free Software Foundation (FSF)</a>
*/
@Experimental
public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
/**
@@ -140,7 +143,8 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -150,7 +154,7 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
}
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File actualFile = dependency.getActualFile();
final String name = actualFile.getName();
@@ -172,11 +176,7 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
}
}
} else {
// copy, alter and set in case some other thread is iterating over
final List<Dependency> deps = new ArrayList<Dependency>(
engine.getDependencies());
deps.remove(dependency);
engine.setDependencies(deps);
engine.getDependencies().remove(dependency);
}
}
@@ -220,14 +220,12 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
*/
private String getFileContents(final File actualFile)
throws AnalysisException {
String contents = "";
try {
contents = FileUtils.readFileToString(actualFile).trim();
return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occured while reading dependency file.", e);
"Problem occurred while reading dependency file.", e);
}
return contents;
}
/**
@@ -270,10 +268,11 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the file type analyzer.
*
* @throws Exception thrown if there is an exception during initialization
* @throws InitializationException thrown if there is an exception during
* initialization
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// No initialization needed.
}
}

View File

@@ -18,7 +18,7 @@
package org.owasp.dependencycheck.analyzer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
@@ -32,23 +32,29 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* <p>
* Used to analyze CMake build files, and collect information that can be used to determine the associated CPE.</p>
* <p/>
* Used to analyze CMake build files, and collect information that can be used
* to determine the associated CPE.</p>
* <p>
* Note: This analyzer catches straightforward invocations of the project command, plus some other observed patterns of version
* inclusion in real CMake projects. Many projects make use of older versions of CMake and/or use custom "homebrew" ways to insert
* version information. Hopefully as the newer CMake call pattern grows in usage, this analyzer allow more CPEs to be
* Note: This analyzer catches straightforward invocations of the project
* command, plus some other observed patterns of version inclusion in real CMake
* projects. Many projects make use of older versions of CMake and/or use custom
* "homebrew" ways to insert version information. Hopefully as the newer CMake
* call pattern grows in usage, this analyzer allow more CPEs to be
* identified.</p>
*
* @author Dale Visser <dvisser@ida.org>
* @author Dale Visser
*/
@Experimental
public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
/**
@@ -62,11 +68,19 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
private static final int REGEX_OPTIONS = Pattern.DOTALL
| Pattern.CASE_INSENSITIVE | Pattern.MULTILINE;
/**
* Regex to extract the product information.
*/
private static final Pattern PROJECT = Pattern.compile(
"^ *project *\\([ \\n]*(\\w+)[ \\n]*.*?\\)", REGEX_OPTIONS);
// Group 1: Product
// Group 2: Version
/**
* Regex to extract product and version information.
*
* Group 1: Product
*
* Group 2: Version
*/
private static final Pattern SET_VERSION = Pattern
.compile(
"^ *set\\s*\\(\\s*(\\w+)_version\\s+\"?(\\d+(?:\\.\\d+)+)[\\s\"]?\\)",
@@ -78,24 +92,10 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(".cmake")
.addFilenames("CMakeLists.txt").build();
/**
* A reference to SHA1 message digest.
*/
private static MessageDigest sha1 = null;
static {
try {
sha1 = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e.getMessage());
}
}
/**
* Returns the name of the CMake analyzer.
*
* @return the name of the analyzer
*
*/
@Override
public String getName() {
@@ -123,13 +123,19 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* No-op initializer implementation.
* Initializes the analyzer.
*
* @throws Exception never thrown
* @throws InitializationException thrown if an exception occurs getting an
* instance of SHA1
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
// Nothing to do here.
protected void initializeFileTypeAnalyzer() throws InitializationException {
try {
getSha1MessageDigest();
} catch (IllegalStateException ex) {
setEnabled(false);
throw new InitializationException("Unable to create SHA1 MessageDigest", ex);
}
}
/**
@@ -137,10 +143,11 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File file = dependency.getActualFile();
final String parentName = file.getParentFile().getName();
@@ -148,7 +155,7 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
dependency.setDisplayFileName(String.format("%s%c%s", parentName, File.separatorChar, name));
String contents;
try {
contents = FileUtils.readFileToString(file).trim();
contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -167,20 +174,32 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getProductEvidence().addEvidence(name, "Project",
group, Confidence.HIGH);
}
LOGGER.debug(String.format("Found %d matches.", count));
LOGGER.debug("Found {} matches.", count);
analyzeSetVersionCommand(dependency, engine, contents);
}
}
/**
* Extracts the version information from the contents. If more then one
* version is found additional dependencies are added to the dependency
* list.
*
* @param dependency the dependency being analyzed
* @param engine the dependency-check engine
* @param contents the version information
*/
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
value = "DM_DEFAULT_ENCODING",
justification = "Default encoding is only used if UTF-8 is not available")
private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) {
final Dependency orig = dependency;
Dependency currentDep = dependency;
final Matcher m = SET_VERSION.matcher(contents);
int count = 0;
while (m.find()) {
count++;
LOGGER.debug(String.format(
"Found project command match with %d groups: %s",
m.groupCount(), m.group(0)));
LOGGER.debug("Found project command match with {} groups: {}",
m.groupCount(), m.group(0));
String product = m.group(1);
final String version = m.group(2);
LOGGER.debug("Group 1: " + product);
@@ -191,19 +210,25 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
}
if (count > 1) {
//TODO - refactor so we do not assign to the parameter (checkstyle)
dependency = new Dependency(orig.getActualFile());
dependency.setDisplayFileName(String.format("%s:%s", orig.getDisplayFileName(), product));
final String filePath = String.format("%s:%s", orig.getFilePath(), product);
dependency.setFilePath(filePath);
currentDep = new Dependency(dependency.getActualFile());
currentDep.setDisplayFileName(String.format("%s:%s", dependency.getDisplayFileName(), product));
final String filePath = String.format("%s:%s", dependency.getFilePath(), product);
currentDep.setFilePath(filePath);
// prevents coalescing into the dependency provided by engine
dependency.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes())));
engine.getDependencies().add(dependency);
byte[] path;
try {
path = filePath.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
path = filePath.getBytes();
}
final MessageDigest sha1 = getSha1MessageDigest();
currentDep.setSha1sum(Checksum.getHex(sha1.digest(path)));
engine.getDependencies().add(currentDep);
}
final String source = dependency.getDisplayFileName();
dependency.getProductEvidence().addEvidence(source, "Product",
final String source = currentDep.getDisplayFileName();
currentDep.getProductEvidence().addEvidence(source, "Product",
product, Confidence.MEDIUM);
dependency.getVersionEvidence().addEvidence(source, "Version",
currentDep.getVersionEvidence().addEvidence(source, "Version",
version, Confidence.MEDIUM);
}
LOGGER.debug(String.format("Found %d matches.", count));
@@ -213,4 +238,18 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_CMAKE_ENABLED;
}
/**
* Returns the sha1 message digest.
*
* @return the sha1 message digest
*/
private MessageDigest getSha1MessageDigest() {
try {
return MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e.getMessage());
throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e);
}
}
}

View File

@@ -25,6 +25,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryparser.classic.ParseException;
@@ -45,18 +47,21 @@ import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* CPEAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated CPE. It uses
* the evidence contained within the dependency to search the Lucene index.
* CPEAnalyzer is a utility class that takes a project dependency and attempts
* to discern if there is an associated CPE. It uses the evidence contained
* within the dependency to search the Lucene index.
*
* @author Jeremy Long
*/
public class CPEAnalyzer implements Analyzer {
public class CPEAnalyzer extends AbstractAnalyzer {
/**
* The Logger.
@@ -65,23 +70,26 @@ public class CPEAnalyzer implements Analyzer {
/**
* The maximum number of query results to return.
*/
static final int MAX_QUERY_RESULTS = 25;
private static final int MAX_QUERY_RESULTS = 25;
/**
* The weighting boost to give terms when constructing the Lucene query.
*/
static final String WEIGHTING_BOOST = "^5";
private static final String WEIGHTING_BOOST = "^5";
/**
* A string representation of a regular expression defining characters utilized within the CPE Names.
* A string representation of a regular expression defining characters
* utilized within the CPE Names.
*/
static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
private static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
/**
* A string representation of a regular expression used to remove all but alpha characters.
* A string representation of a regular expression used to remove all but
* alpha characters.
*/
static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
private static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*";
/**
* The additional size to add to a new StringBuilder to account for extra data that will be written into the string.
* The additional size to add to a new StringBuilder to account for extra
* data that will be written into the string.
*/
static final int STRING_BUILDER_BUFFER = 20;
private static final int STRING_BUILDER_BUFFER = 20;
/**
* The CPE in memory index.
*/
@@ -117,33 +125,55 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Creates the CPE Lucene Index.
* The default is to support parallel processing.
*
* @throws Exception is thrown if there is an issue opening the index.
* @return false
*/
@Override
public void initialize() throws Exception {
this.open();
public boolean supportsParallelProcessing() {
return false;
}
/**
* Creates the CPE Lucene Index.
*
* @throws InitializationException is thrown if there is an issue opening
* the index.
*/
@Override
public void initializeAnalyzer() throws InitializationException {
try {
this.open();
} catch (IOException ex) {
LOGGER.debug("Exception initializing the Lucene Index", ex);
throw new InitializationException("An exception occurred initializing the Lucene Index", ex);
} catch (DatabaseException ex) {
LOGGER.debug("Exception accessing the database", ex);
throw new InitializationException("An exception occurred accessing the database", ex);
}
}
/**
* Opens the data source.
*
* @throws IOException when the Lucene directory to be queried does not exist or is corrupt.
* @throws DatabaseException when the database throws an exception. This usually occurs when the database is in use by another
* process.
* @throws IOException when the Lucene directory to be queried does not
* exist or is corrupt.
* @throws DatabaseException when the database throws an exception. This
* usually occurs when the database is in use by another process.
*/
public void open() throws IOException, DatabaseException {
LOGGER.debug("Opening the CVE Database");
cve = new CveDB();
cve.open();
LOGGER.debug("Creating the Lucene CPE Index");
cpe = CpeMemoryIndex.getInstance();
try {
cpe.open(cve);
} catch (IndexException ex) {
LOGGER.debug("IndexException", ex);
throw new DatabaseException(ex);
if (!isOpen()) {
cve = CveDB.getInstance();
cpe = CpeMemoryIndex.getInstance();
try {
final long creationStart = System.currentTimeMillis();
cpe.open(cve);
final long creationSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - creationStart);
LOGGER.info("Created CPE Index ({} seconds)", creationSeconds);
} catch (IndexException ex) {
LOGGER.debug("IndexException", ex);
throw new DatabaseException(ex);
}
}
}
@@ -151,24 +181,30 @@ public class CPEAnalyzer implements Analyzer {
* Closes the data sources.
*/
@Override
public void close() {
if (cpe != null) {
cpe.close();
cpe = null;
}
public void closeAnalyzer() {
if (cve != null) {
cve.close();
cve = null;
}
if (cpe != null) {
cpe.close();
cpe = null;
}
}
/**
* Returns whether or not the analyzer is open.
*
* @return <code>true</code> if the analyzer is open
*/
public boolean isOpen() {
return cpe != null && cpe.isOpen();
}
/**
* Searches the data store of CPE entries, trying to identify the CPE for the given dependency based on the evidence contained
* within. The dependency passed in is updated with any identified CPE values.
* Searches the data store of CPE entries, trying to identify the CPE for
* the given dependency based on the evidence contained within. The
* dependency passed in is updated with any identified CPE values.
*
* @param dependency the dependency to search for CPE entries on.
* @throws CorruptIndexException is thrown when the Lucene index is corrupt.
@@ -176,7 +212,7 @@ public class CPEAnalyzer implements Analyzer {
* @throws ParseException is thrown when the Lucene query cannot be parsed.
*/
protected void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
//TODO test dojo-war against this. we shold get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
//TODO test dojo-war against this. we should get dojo-toolkit:dojo-toolkit AND dojo-toolkit:toolkit
String vendors = "";
String products = "";
for (Confidence confidence : Confidence.values()) {
@@ -189,8 +225,8 @@ public class CPEAnalyzer implements Analyzer {
LOGGER.debug("product search: {}", products);
}
if (!vendors.isEmpty() && !products.isEmpty()) {
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getProductEvidence().getWeighting(),
dependency.getVendorEvidence().getWeighting());
final List<IndexEntry> entries = searchCPE(vendors, products, dependency.getVendorEvidence().getWeighting(),
dependency.getProductEvidence().getWeighting());
if (entries == null) {
continue;
}
@@ -212,9 +248,10 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Returns the text created by concatenating the text and the values from the EvidenceCollection (filtered for a specific
* confidence). This attempts to prevent duplicate terms from being added.<br/<br/> Note, if the evidence is longer then 200
* characters it will be truncated.
* Returns the text created by concatenating the text and the values from
* the EvidenceCollection (filtered for a specific confidence). This
* attempts to prevent duplicate terms from being added.<br/<br/> Note, if
* the evidence is longer then 200 characters it will be truncated.
*
* @param text the base text.
* @param ec an EvidenceCollection
@@ -245,23 +282,25 @@ public class CPEAnalyzer implements Analyzer {
/**
* <p>
* Searches the Lucene CPE index to identify possible CPE entries associated with the supplied vendor, product, and
* version.</p>
* Searches the Lucene CPE index to identify possible CPE entries associated
* with the supplied vendor, product, and version.</p>
*
* <p>
* If either the vendorWeightings or productWeightings lists have been populated this data is used to add weighting factors to
* the search.</p>
* If either the vendorWeightings or productWeightings lists have been
* populated this data is used to add weighting factors to the search.</p>
*
* @param vendor the text used to search the vendor field
* @param product the text used to search the product field
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search
* @param vendorWeightings a list of strings to use to add weighting factors
* to the vendor field
* @param productWeightings Adds a list of strings that will be used to add
* weighting factors to the product search
* @return a list of possible CPE values
*/
protected List<IndexEntry> searchCPE(String vendor, String product,
Set<String> vendorWeightings, Set<String> productWeightings) {
final List<IndexEntry> ret = new ArrayList<IndexEntry>(MAX_QUERY_RESULTS);
final List<IndexEntry> ret = new ArrayList<>(MAX_QUERY_RESULTS);
final String searchString = buildSearch(vendor, product, vendorWeightings, productWeightings);
if (searchString == null) {
@@ -283,10 +322,10 @@ public class CPEAnalyzer implements Analyzer {
}
return ret;
} catch (ParseException ex) {
LOGGER.warn("An error occured querying the CPE data. See the log for more details.");
LOGGER.warn("An error occurred querying the CPE data. See the log for more details.");
LOGGER.info("Unable to parse: {}", searchString, ex);
} catch (IOException ex) {
LOGGER.warn("An error occured reading CPE data. See the log for more details.");
LOGGER.warn("An error occurred reading CPE data. See the log for more details.");
LOGGER.info("IO Error with search string: {}", searchString, ex);
}
return null;
@@ -294,16 +333,20 @@ public class CPEAnalyzer implements Analyzer {
/**
* <p>
* Builds a Lucene search string by properly escaping data and constructing a valid search query.</p>
* Builds a Lucene search string by properly escaping data and constructing
* a valid search query.</p>
*
* <p>
* If either the possibleVendor or possibleProducts lists have been populated this data is used to add weighting factors to
* the search string generated.</p>
* If either the possibleVendor or possibleProducts lists have been
* populated this data is used to add weighting factors to the search string
* generated.</p>
*
* @param vendor text to search the vendor field
* @param product text to search the product field
* @param vendorWeighting a list of strings to apply to the vendor to boost the terms weight
* @param productWeightings a list of strings to apply to the product to boost the terms weight
* @param vendorWeighting a list of strings to apply to the vendor to boost
* the terms weight
* @param productWeightings a list of strings to apply to the product to
* boost the terms weight
* @return the Lucene query
*/
protected String buildSearch(String vendor, String product,
@@ -324,21 +367,25 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* This method constructs a Lucene query for a given field. The searchText is split into separate words and if the word is
* within the list of weighted words then an additional weighting is applied to the term as it is appended into the query.
* This method constructs a Lucene query for a given field. The searchText
* is split into separate words and if the word is within the list of
* weighted words then an additional weighting is applied to the term as it
* is appended into the query.
*
* @param sb a StringBuilder that the query text will be appended to.
* @param field the field within the Lucene index that the query is searching.
* @param field the field within the Lucene index that the query is
* searching.
* @param searchText text used to construct the query.
* @param weightedText a list of terms that will be considered higher importance when searching.
* @param weightedText a list of terms that will be considered higher
* importance when searching.
* @return if the append was successful.
*/
private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
sb.append(" ").append(field).append(":( ");
sb.append(' ').append(field).append(":( ");
final String cleanText = cleanseText(searchText);
if ("".equals(cleanText)) {
if (cleanText.isEmpty()) {
return false;
}
@@ -348,20 +395,27 @@ public class CPEAnalyzer implements Analyzer {
final StringTokenizer tokens = new StringTokenizer(cleanText);
while (tokens.hasMoreElements()) {
final String word = tokens.nextToken();
String temp = null;
StringBuilder temp = null;
for (String weighted : weightedText) {
final String weightedStr = cleanseText(weighted);
if (equalsIgnoreCaseAndNonAlpha(word, weightedStr)) {
temp = LuceneUtils.escapeLuceneQuery(word) + WEIGHTING_BOOST;
temp = new StringBuilder(word.length() + 2);
LuceneUtils.appendEscapedLuceneQuery(temp, word);
temp.append(WEIGHTING_BOOST);
if (!word.equalsIgnoreCase(weightedStr)) {
temp += " " + LuceneUtils.escapeLuceneQuery(weightedStr) + WEIGHTING_BOOST;
temp.append(' ');
LuceneUtils.appendEscapedLuceneQuery(temp, weightedStr);
temp.append(WEIGHTING_BOOST);
}
break;
}
}
sb.append(' ');
if (temp == null) {
temp = LuceneUtils.escapeLuceneQuery(word);
LuceneUtils.appendEscapedLuceneQuery(sb, word);
} else {
sb.append(temp);
}
sb.append(" ").append(temp);
}
}
sb.append(" ) ");
@@ -369,7 +423,8 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Removes characters from the input text that are not used within the CPE index.
* Removes characters from the input text that are not used within the CPE
* index.
*
* @param text is the text to remove the characters from.
* @return the text having removed some characters.
@@ -379,7 +434,8 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Compares two strings after lower casing them and removing the non-alpha characters.
* Compares two strings after lower casing them and removing the non-alpha
* characters.
*
* @param l string one to compare.
* @param r string two to compare.
@@ -396,8 +452,9 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Ensures that the CPE Identified matches the dependency. This validates that the product, vendor, and version information
* for the CPE are contained within the dependencies evidence.
* Ensures that the CPE Identified matches the dependency. This validates
* that the product, vendor, and version information for the CPE are
* contained within the dependencies evidence.
*
* @param entry a CPE entry.
* @param dependency the dependency that the CPE entries could be for.
@@ -429,7 +486,7 @@ public class CPEAnalyzer implements Analyzer {
return false;
}
final String[] words = text.split("[\\s_-]");
final List<String> list = new ArrayList<String>();
final List<String> list = new ArrayList<>();
String tempWord = null;
for (String word : words) {
/*
@@ -464,14 +521,16 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Analyzes a dependency and attempts to determine if there are any CPE identifiers for this dependency.
* Analyzes a dependency and attempts to determine if there are any CPE
* identifiers for this dependency.
*
* @param dependency The Dependency to analyze.
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the dependency.
* @throws AnalysisException is thrown if there is an issue analyzing the
* dependency.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
try {
determineCPE(dependency);
} catch (CorruptIndexException ex) {
@@ -484,15 +543,19 @@ public class CPEAnalyzer implements Analyzer {
}
/**
* Retrieves a list of CPE values from the CveDB based on the vendor and product passed in. The list is then validated to find
* only CPEs that are valid for the given dependency. It is possible that the CPE identified is a best effort "guess" based on
* the vendor, product, and version information.
* Retrieves a list of CPE values from the CveDB based on the vendor and
* product passed in. The list is then validated to find only CPEs that are
* valid for the given dependency. It is possible that the CPE identified is
* a best effort "guess" based on the vendor, product, and version
* information.
*
* @param dependency the Dependency being analyzed
* @param vendor the vendor for the CPE being analyzed
* @param product the product for the CPE being analyzed
* @param currentConfidence the current confidence being used during analysis
* @return <code>true</code> if an identifier was added to the dependency; otherwise <code>false</code>
* @param currentConfidence the current confidence being used during
* analysis
* @return <code>true</code> if an identifier was added to the dependency;
* otherwise <code>false</code>
* @throws UnsupportedEncodingException is thrown if UTF-8 is not supported
*/
protected boolean determineIdentifiers(Dependency dependency, String vendor, String product,
@@ -501,11 +564,12 @@ public class CPEAnalyzer implements Analyzer {
DependencyVersion bestGuess = new DependencyVersion("-");
Confidence bestGuessConf = null;
boolean hasBroadMatch = false;
final List<IdentifierMatch> collected = new ArrayList<IdentifierMatch>();
final List<IdentifierMatch> collected = new ArrayList<>();
//TODO the following algorithm incorrectly identifies things as a lower version
// if there lower confidence evidence when the current (highest) version number
// is newer then anything in the NVD.
for (Confidence conf : Confidence.values()) {
// if (conf.compareTo(currentConfidence) > 0) {
// break;
// }
for (Evidence evidence : dependency.getVersionEvidence().iterator(conf)) {
final DependencyVersion evVer = DependencyVersionUtil.parseVersion(evidence.getValue());
if (evVer == null) {
@@ -514,7 +578,7 @@ public class CPEAnalyzer implements Analyzer {
for (VulnerableSoftware vs : cpes) {
DependencyVersion dbVer;
if (vs.getUpdate() != null && !vs.getUpdate().isEmpty()) {
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + "." + vs.getUpdate());
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion() + '.' + vs.getUpdate());
} else {
dbVer = DependencyVersionUtil.parseVersion(vs.getVersion());
}
@@ -527,24 +591,22 @@ public class CPEAnalyzer implements Analyzer {
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
collected.add(match);
} else {
//TODO the following isn't quite right is it? need to think about this guessing game a bit more.
if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
bestGuess = dbVer;
bestGuessConf = conf;
}
} else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
bestGuess = dbVer;
bestGuessConf = conf;
}
}
}
}
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
if (bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
bestGuess = evVer;
bestGuessConf = conf;
}
if ((bestGuessConf == null || bestGuessConf.compareTo(conf) > 0)
&& bestGuess.getVersionParts().size() < evVer.getVersionParts().size()) {
bestGuess = evVer;
bestGuessConf = conf;
}
}
}
@@ -554,10 +616,12 @@ public class CPEAnalyzer implements Analyzer {
final String cpeUrlName = String.format("cpe:/a:%s:%s", vendor, product);
url = String.format(NVD_SEARCH_URL, URLEncoder.encode(cpeUrlName, "UTF-8"));
}
if (bestGuessConf == null) {
if (bestGuessConf
== null) {
bestGuessConf = Confidence.LOW;
}
final IdentifierMatch match = new IdentifierMatch("cpe", cpeName, url, IdentifierConfidence.BEST_GUESS, bestGuessConf);
collected.add(match);
Collections.sort(collected);
@@ -580,6 +644,18 @@ public class CPEAnalyzer implements Analyzer {
return identifierAdded;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_CPE_ENABLED;
}
/**
* The confidence whether the identifier is an exact match, or a best guess.
*/
@@ -594,37 +670,50 @@ public class CPEAnalyzer implements Analyzer {
*/
BEST_GUESS,
/**
* The entire vendor/product group must be added (without a guess at version) because there is a CVE with a VS that only
* specifies vendor/product.
* The entire vendor/product group must be added (without a guess at
* version) because there is a CVE with a VS that only specifies
* vendor/product.
*/
BROAD_MATCH
}
/**
* A simple object to hold an identifier and carry information about the confidence in the identifier.
* A simple object to hold an identifier and carry information about the
* confidence in the identifier.
*/
private static class IdentifierMatch implements Comparable<IdentifierMatch> {
/**
* The confidence in the evidence used to identify this match.
*/
private Confidence evidenceConfidence;
/**
* The confidence whether this is an exact match, or a best guess.
*/
private IdentifierConfidence confidence;
/**
* The CPE identifier.
*/
private Identifier identifier;
/**
* Constructs an IdentifierMatch.
*
* @param type the type of identifier (such as CPE)
* @param value the value of the identifier
* @param url the URL of the identifier
* @param identifierConfidence the confidence in the identifier: best guess or exact match
* @param evidenceConfidence the confidence of the evidence used to find the identifier
* @param identifierConfidence the confidence in the identifier: best
* guess or exact match
* @param evidenceConfidence the confidence of the evidence used to find
* the identifier
*/
IdentifierMatch(String type, String value, String url, IdentifierConfidence identifierConfidence, Confidence evidenceConfidence) {
this.identifier = new Identifier(type, value, url);
this.confidence = identifierConfidence;
this.evidenceConfidence = evidenceConfidence;
}
//<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
/**
* The confidence in the evidence used to identify this match.
*/
private Confidence evidenceConfidence;
//<editor-fold defaultstate="collapsed" desc="Property implementations: evidenceConfidence, confidence, identifier">
/**
* Get the value of evidenceConfidence
*
@@ -642,10 +731,6 @@ public class CPEAnalyzer implements Analyzer {
public void setEvidenceConfidence(Confidence evidenceConfidence) {
this.evidenceConfidence = evidenceConfidence;
}
/**
* The confidence whether this is an exact match, or a best guess.
*/
private IdentifierConfidence confidence;
/**
* Get the value of confidence.
@@ -664,10 +749,6 @@ public class CPEAnalyzer implements Analyzer {
public void setConfidence(IdentifierConfidence confidence) {
this.confidence = confidence;
}
/**
* The CPE identifier.
*/
private Identifier identifier;
/**
* Get the value of identifier.
@@ -735,29 +816,24 @@ public class CPEAnalyzer implements Analyzer {
if (this.confidence != other.confidence) {
return false;
}
if (this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier))) {
return false;
}
return true;
return !(this.identifier != other.identifier && (this.identifier == null || !this.identifier.equals(other.identifier)));
}
//</editor-fold>
/**
* Standard implementation of compareTo that compares identifier confidence, evidence confidence, and then the identifier.
* Standard implementation of compareTo that compares identifier
* confidence, evidence confidence, and then the identifier.
*
* @param o the IdentifierMatch to compare to
* @return the natural ordering of IdentifierMatch
*/
@Override
public int compareTo(IdentifierMatch o) {
int conf = this.confidence.compareTo(o.confidence);
if (conf == 0) {
conf = this.evidenceConfidence.compareTo(o.evidenceConfidence);
if (conf == 0) {
conf = identifier.compareTo(o.identifier);
}
}
return conf;
return new CompareToBuilder()
.append(confidence, o.confidence)
.append(evidenceConfidence, o.evidenceConfidence)
.append(identifier, o.identifier)
.toComparison();
}
}
}

View File

@@ -33,8 +33,10 @@ import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
@@ -42,8 +44,8 @@ import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will attempt to locate a dependency, and the GAV information, by querying Central for the dependency's SHA-1
* digest.
* Analyzer which will attempt to locate a dependency, and the GAV information,
* by querying Central for the dependency's SHA-1 digest.
*
* @author colezlaw
*/
@@ -70,9 +72,10 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
private static final String SUPPORTED_EXTENSIONS = "jar";
/**
* The analyzer should be disabled if there are errors, so this is a flag to determine if such an error has occurred.
* The analyzer should be disabled if there are errors, so this is a flag to
* determine if such an error has occurred.
*/
private boolean errorFlag = false;
private volatile boolean errorFlag = false;
/**
* The searcher itself.
@@ -96,17 +99,18 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Determines if this analyzer is enabled.
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
* @return <code>true</code> if the analyzer is enabled; otherwise
* <code>false</code>
*/
private boolean checkEnabled() {
boolean retval = false;
boolean retVal = false;
try {
if (Settings.getBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED)) {
if (!Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)
|| NexusAnalyzer.DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))) {
LOGGER.debug("Enabling the Central analyzer");
retval = true;
retVal = true;
} else {
LOGGER.info("Nexus analyzer is enabled, disabling the Central Analyzer");
}
@@ -116,22 +120,27 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
} catch (InvalidSettingException ise) {
LOGGER.warn("Invalid setting. Disabling the Central analyzer");
}
return retval;
return retVal;
}
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
LOGGER.debug("Initializing Central analyzer");
LOGGER.debug("Central analyzer enabled: {}", isEnabled());
if (isEnabled()) {
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
LOGGER.debug("Central Analyzer URL: {}", searchUrl);
searcher = new CentralSearch(new URL(searchUrl));
try {
searcher = new CentralSearch(new URL(searchUrl));
} catch (MalformedURLException ex) {
setEnabled(false);
throw new InitializationException("The configured URL to Maven Central is malformed: " + searchUrl, ex);
}
}
}
@@ -146,7 +155,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to to reference the analyzer's enabled property.
* Returns the key used in the properties file to to reference the
* analyzer's enabled property.
*
* @return the analyzer's enabled property setting key.
*/
@@ -183,7 +193,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
if (errorFlag || !isEnabled()) {
return;
}
@@ -192,7 +202,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
final List<MavenArtifact> mas = searcher.searchSha1(dependency.getSha1sum());
final Confidence confidence = mas.size() > 1 ? Confidence.HIGH : Confidence.HIGHEST;
for (MavenArtifact ma : mas) {
LOGGER.debug("Central analyzer found artifact ({}) for dependency ({})", ma.toString(), dependency.getFileName());
LOGGER.debug("Central analyzer found artifact ({}) for dependency ({})", ma, dependency.getFileName());
dependency.addAsEvidence("central", ma, confidence);
boolean pomAnalyzed = false;
for (Evidence e : dependency.getVendorEvidence()) {
@@ -219,7 +229,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.warn("Unable to download pom.xml for {} from Central; "
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
} finally {
if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
pomFile.deleteOnExit();
}
}

View File

@@ -0,0 +1,205 @@
/*
* 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) 2016 IBM Corporation. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
/**
* This analyzer is used to analyze SWIFT and Objective-C packages by collecting
* information from .podspec files. CocoaPods dependency manager see
* https://cocoapods.org/.
*
* @author Bianca Jiang (https://twitter.com/biancajiang)
*/
@Experimental
public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
// private static final Logger LOGGER = LoggerFactory.getLogger(CocoaPodsAnalyzer.class);
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "CocoaPods Package Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The file name to scan.
*/
public static final String PODSPEC = "podspec";
/**
* Filter that detects files named "*.podspec".
*/
private static final FileFilter PODSPEC_FILTER = FileFilterBuilder.newInstance().addExtensions(PODSPEC).build();
/**
* The capture group #1 is the block variable. e.g. "Pod::Spec.new do
* |spec|"
*/
private static final Pattern PODSPEC_BLOCK_PATTERN = Pattern.compile("Pod::Spec\\.new\\s+?do\\s+?\\|(.+?)\\|");
/**
* Returns the FileFilter
*
* @return the FileFilter
*/
@Override
protected FileFilter getFileFilter() {
return PODSPEC_FILTER;
}
@Override
protected void initializeFileTypeAnalyzer() {
// NO-OP
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_COCOAPODS_ENABLED;
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
String contents;
try {
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
}
final Matcher matcher = PODSPEC_BLOCK_PATTERN.matcher(contents);
if (matcher.find()) {
contents = contents.substring(matcher.end());
final String blockVariable = matcher.group(1);
final EvidenceCollection vendor = dependency.getVendorEvidence();
final EvidenceCollection product = dependency.getProductEvidence();
final EvidenceCollection version = dependency.getVersionEvidence();
final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
if (!name.isEmpty()) {
vendor.addEvidence(PODSPEC, "name_project", name, Confidence.HIGHEST);
}
addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
addStringEvidence(version, contents, blockVariable, "version", "version", Confidence.HIGHEST);
}
setPackagePath(dependency);
}
/**
* Extracts evidence from the contents and adds it to the given evidence
* collection.
*
* @param evidences the evidence collection to update
* @param contents the text to extract evidence from
* @param blockVariable the block variable within the content to search for
* @param field the name of the field being searched for
* @param fieldPattern the field pattern within the contents to search for
* @param confidence the confidence level of the evidence if found
* @return the string that was added as evidence
*/
private String addStringEvidence(EvidenceCollection evidences, String contents,
String blockVariable, String field, String fieldPattern, Confidence confidence) {
String value = "";
//capture array value between [ ]
final Matcher arrayMatcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?\\{\\s*?(.*?)\\s*?\\}", blockVariable, fieldPattern),
Pattern.CASE_INSENSITIVE).matcher(contents);
if (arrayMatcher.find()) {
value = arrayMatcher.group(1);
} else { //capture single value between quotes
final Matcher matcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern),
Pattern.CASE_INSENSITIVE).matcher(contents);
if (matcher.find()) {
value = matcher.group(2);
}
}
if (value.length() > 0) {
evidences.addEvidence(PODSPEC, field, value, confidence);
}
return value;
}
/**
* Sets the package path on the given dependency.
*
* @param dep the dependency to update
*/
private void setPackagePath(Dependency dep) {
final File file = new File(dep.getFilePath());
final String parent = file.getParent();
if (parent != null) {
dep.setPackagePath(parent);
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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) 2015 The OWASP Foundation. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.composer.ComposerDependency;
import org.owasp.dependencycheck.data.composer.ComposerException;
import org.owasp.dependencycheck.data.composer.ComposerLockParser;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Checksum;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Used to analyze a composer.lock file for a composer PHP app.
*
* @author colezlaw
*/
@Experimental
public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockAnalyzer.class);
/**
* The analyzer name.
*/
private static final String ANALYZER_NAME = "Composer.lock analyzer";
/**
* composer.json.
*/
private static final String COMPOSER_LOCK = "composer.lock";
/**
* The FileFilter.
*/
private static final FileFilter FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(COMPOSER_LOCK).build();
/**
* Returns the FileFilter.
*
* @return the FileFilter
*/
@Override
protected FileFilter getFileFilter() {
return FILE_FILTER;
}
/**
* Initializes the analyzer.
*
* @throws InitializationException thrown if an exception occurs getting an
* instance of SHA1
*/
@Override
protected void initializeFileTypeAnalyzer() throws InitializationException {
try {
getSha1MessageDigest();
} catch (IllegalStateException ex) {
setEnabled(false);
throw new InitializationException("Unable to create SHA1 MessageDigest", ex);
}
}
/**
* Entry point for the analyzer.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
* @throws AnalysisException if there's a failure during analysis
*/
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
try (FileInputStream fis = new FileInputStream(dependency.getActualFile())) {
final ComposerLockParser clp = new ComposerLockParser(fis);
LOGGER.info("Checking composer.lock file {}", dependency.getActualFilePath());
clp.process();
for (ComposerDependency dep : clp.getDependencies()) {
final Dependency d = new Dependency(dependency.getActualFile());
d.setDisplayFileName(String.format("%s:%s/%s", dependency.getDisplayFileName(), dep.getGroup(), dep.getProject()));
final String filePath = String.format("%s:%s/%s", dependency.getFilePath(), dep.getGroup(), dep.getProject());
final MessageDigest sha1 = getSha1MessageDigest();
d.setFilePath(filePath);
d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset()))));
d.getVendorEvidence().addEvidence(COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST);
d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST);
d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST);
LOGGER.info("Adding dependency {}", d);
engine.getDependencies().add(d);
}
} catch (IOException ex) {
LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath());
} catch (ComposerException ce) {
LOGGER.warn("Error parsing composer.json {}", dependency.getActualFilePath(), ce);
}
}
/**
* Gets the key to determine whether the analyzer is enabled.
*
* @return the key specifying whether the analyzer is enabled
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED;
}
/**
* Returns the analyzer's name.
*
* @return the analyzer's name
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase this analyzer should run under.
*
* @return the analysis phase
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return AnalysisPhase.INFORMATION_COLLECTION;
}
/**
* Returns the sha1 message digest.
*
* @return the sha1 message digest
*/
private MessageDigest getSha1MessageDigest() {
try {
return MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
LOGGER.error(e.getMessage());
throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e);
}
}
}

View File

@@ -20,7 +20,8 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
/**
* The suppression analyzer processes an externally defined XML document that complies with the suppressions.xsd schema.
@@ -62,7 +63,7 @@ public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
//</editor-fold>
@Override
public void analyze(final Dependency dependency, final Engine engine) throws AnalysisException {
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
if (getRules() == null || getRules().size() <= 0) {
return;
@@ -72,4 +73,15 @@ public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer {
rule.process(dependency);
}
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_CPE_SUPPRESSION_ENABLED;
}
}

View File

@@ -30,20 +30,24 @@ import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* This analyzer ensures dependencies that should be grouped together, to remove excess noise from the report, are grouped. An
* example would be Spring, Spring Beans, Spring MVC, etc. If they are all for the same version and have the same relative path
* then these should be grouped into a single dependency under the core/main library.</p>
* This analyzer ensures dependencies that should be grouped together, to remove
* excess noise from the report, are grouped. An example would be Spring, Spring
* Beans, Spring MVC, etc. If they are all for the same version and have the
* same relative path then these should be grouped into a single dependency
* under the core/main library.</p>
* <p>
* Note, this grouping only works on dependencies with identified CVE entries</p>
* Note, this grouping only works on dependencies with identified CVE
* entries</p>
*
* @author Jeremy Long
*/
public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Analyzer {
public class DependencyBundlingAnalyzer extends AbstractAnalyzer {
/**
* The Logger.
@@ -55,10 +59,23 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* A pattern for obtaining the first part of a filename.
*/
private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*");
/**
* a flag indicating if this analyzer has run. This analyzer only runs once.
*/
private boolean analyzed = false;
/**
* Returns a flag indicating if this analyzer has run. This analyzer only
* runs once. Note this is currently only used in the unit tests.
*
* @return a flag indicating if this analyzer has run. This analyzer only
* runs once
*/
protected synchronized boolean getAnalyzed() {
return analyzed;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
@@ -68,13 +85,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_FINDING_ANALYSIS;
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.FINAL;
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
@@ -84,24 +102,50 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
//</editor-fold>
/**
* Analyzes a set of dependencies. If they have been found to have the same base path and the same set of identifiers they are
* likely related. The related dependencies are bundled into a single reportable item.
* Does not support parallel processing as it only runs once and then
* operates on <em>all</em> dependencies.
*
* @return whether or not parallel processing is enabled
* @see #analyze(Dependency, Engine)
*/
@Override
public boolean supportsParallelProcessing() {
return false;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_DEPENDENCY_BUNDLING_ENABLED;
}
/**
* Analyzes a set of dependencies. If they have been found to have the same
* base path and the same set of identifiers they are likely related. The
* related dependencies are bundled into a single reportable item.
*
* @param ignore this analyzer ignores the dependency being analyzed
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyze(Dependency ignore, Engine engine) throws AnalysisException {
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
if (!analyzed) {
analyzed = true;
final Set<Dependency> dependenciesToRemove = new HashSet<Dependency>();
final Set<Dependency> dependenciesToRemove = new HashSet<>();
final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
//for (Dependency nextDependency : engine.getDependencies()) {
while (mainIterator.hasNext()) {
@@ -110,13 +154,15 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
while (subIterator.hasNext()) {
final Dependency nextDependency = subIterator.next();
if (hashesMatch(dependency, nextDependency) && !containedInWar(dependency.getFilePath())
&& !containedInWar(nextDependency.getFilePath())) {
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
break; //since we merged into the next dependency - skip forward to the next in mainIterator
if (hashesMatch(dependency, nextDependency)) {
if (!containedInWar(dependency.getFilePath())
&& !containedInWar(nextDependency.getFilePath())) {
if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
break; //since we merged into the next dependency - skip forward to the next in mainIterator
}
}
} else if (isShadedJar(dependency, nextDependency)) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) {
@@ -129,6 +175,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
} else if (cpeIdentifiersMatch(dependency, nextDependency)
&& hasSameBasePath(dependency, nextDependency)
&& vulnCountMatches(dependency, nextDependency)
&& fileNameMatch(dependency, nextDependency)) {
if (isCore(dependency, nextDependency)) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
@@ -150,10 +197,11 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* Adds the relatedDependency to the dependency's related dependencies.
*
* @param dependency the main dependency
* @param relatedDependency a collection of dependencies to be removed from the main analysis loop, this is the source of
* dependencies to remove
* @param dependenciesToRemove a collection of dependencies that will be removed from the main analysis loop, this function
* adds to this collection
* @param relatedDependency a collection of dependencies to be removed from
* the main analysis loop, this is the source of dependencies to remove
* @param dependenciesToRemove a collection of dependencies that will be
* removed from the main analysis loop, this function adds to this
* collection
*/
private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
dependency.addRelatedDependency(relatedDependency);
@@ -169,13 +217,19 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Attempts to trim a maven repo to a common base path. This is typically [drive]\[repo_location]\repository\[path1]\[path2].
* Attempts to trim a maven repo to a common base path. This is typically
* [drive]\[repo_location]\repository\[path1]\[path2].
*
* @param path the path to trim
* @return a string representing the base path.
*/
private String getBaseRepoPath(final String path) {
int pos = path.indexOf("repository" + File.separator) + 11;
int pos;
if (path.contains("local-repo")) {
pos = path.indexOf("local-repo" + File.separator) + 11;
} else {
pos = path.indexOf("repository" + File.separator) + 11;
}
if (pos < 0) {
return path;
}
@@ -194,11 +248,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Returns true if the file names (and version if it exists) of the two dependencies are sufficiently similar.
* Returns true if the file names (and version if it exists) of the two
* dependencies are sufficiently similar.
*
* @param dependency1 a dependency2 to compare
* @param dependency2 a dependency2 to compare
* @return true if the identifiers in the two supplied dependencies are equal
* @return true if the identifiers in the two supplied dependencies are
* equal
*/
private boolean fileNameMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency1.getFileName() == null
@@ -211,10 +267,8 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
//version check
final DependencyVersion version1 = DependencyVersionUtil.parseVersion(fileName1);
final DependencyVersion version2 = DependencyVersionUtil.parseVersion(fileName2);
if (version1 != null && version2 != null) {
if (!version1.equals(version2)) {
return false;
}
if (version1 != null && version2 != null && !version1.equals(version2)) {
return false;
}
//filename check
@@ -228,11 +282,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Returns true if the CPE identifiers in the two supplied dependencies are equal.
* Returns true if the CPE identifiers in the two supplied dependencies are
* equal.
*
* @param dependency1 a dependency2 to compare
* @param dependency2 a dependency2 to compare
* @return true if the identifiers in the two supplied dependencies are equal
* @return true if the identifiers in the two supplied dependencies are
* equal
*/
private boolean cpeIdentifiersMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency1.getIdentifiers() == null
@@ -266,6 +322,19 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
return matches;
}
/**
* Returns true if the two dependencies have the same vulnerability count.
*
* @param dependency1 a dependency2 to compare
* @param dependency2 a dependency2 to compare
* @return true if the two dependencies have the same vulnerability count
*/
private boolean vulnCountMatches(Dependency dependency1, Dependency dependency2) {
return dependency1.getVulnerabilities() != null && dependency2.getVulnerabilities() != null
&& dependency1.getVulnerabilities().size() == dependency2.getVulnerabilities().size();
}
/**
* Determines if the two dependencies have the same base path.
*
@@ -283,11 +352,14 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
String right = rFile.getParent();
if (left == null) {
return right == null;
} else if (right == null) {
return false;
}
if (left.equalsIgnoreCase(right)) {
return true;
}
if (left.matches(".*[/\\\\]repository[/\\\\].*") && right.matches(".*[/\\\\]repository[/\\\\].*")) {
if (left.matches(".*[/\\\\](repository|local-repo)[/\\\\].*") && right.matches(".*[/\\\\](repository|local-repo)[/\\\\].*")) {
left = getBaseRepoPath(left);
right = getBaseRepoPath(right);
}
@@ -304,14 +376,15 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* This is likely a very broken attempt at determining if the 'left' dependency is the 'core' library in comparison to the
* 'right' library.
* This is likely a very broken attempt at determining if the 'left'
* dependency is the 'core' library in comparison to the 'right' library.
*
* @param left the dependency to test
* @param right the dependency to test against
* @return a boolean indicating whether or not the left dependency should be considered the "core" version.
* @return a boolean indicating whether or not the left dependency should be
* considered the "core" version.
*/
boolean isCore(Dependency left, Dependency right) {
protected boolean isCore(Dependency left, Dependency right) {
final String leftName = left.getFileName().toLowerCase();
final String rightName = right.getFileName().toLowerCase();
@@ -324,10 +397,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
|| !rightName.contains("core") && leftName.contains("core")
|| !rightName.contains("kernel") && leftName.contains("kernel")) {
returnVal = true;
// } else if (leftName.matches(".*struts2\\-core.*") && rightName.matches(".*xwork\\-core.*")) {
// returnVal = true;
// } else if (rightName.matches(".*struts2\\-core.*") && leftName.matches(".*xwork\\-core.*")) {
// returnVal = false;
} else {
/*
* considered splitting the names up and comparing the components,
@@ -345,11 +414,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Compares the SHA1 hashes of two dependencies to determine if they are equal.
* Compares the SHA1 hashes of two dependencies to determine if they are
* equal.
*
* @param dependency1 a dependency object to compare
* @param dependency2 a dependency object to compare
* @return true if the sha1 hashes of the two dependencies match; otherwise false
* @return true if the sha1 hashes of the two dependencies match; otherwise
* false
*/
private boolean hashesMatch(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency2 == null || dependency1.getSha1sum() == null || dependency2.getSha1sum() == null) {
@@ -359,12 +430,13 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Determines if the jar is shaded and the created pom.xml identified the same CPE as the jar - if so, the pom.xml dependency
* should be removed.
* Determines if the jar is shaded and the created pom.xml identified the
* same CPE as the jar - if so, the pom.xml dependency should be removed.
*
* @param dependency a dependency to check
* @param nextDependency another dependency to check
* @return true if on of the dependencies is a pom.xml and the identifiers between the two collections match; otherwise false
* @return true if on of the dependencies is a pom.xml and the identifiers
* between the two collections match; otherwise false
*/
private boolean isShadedJar(Dependency dependency, Dependency nextDependency) {
final String mainName = dependency.getFileName().toLowerCase();
@@ -378,14 +450,18 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
}
/**
* Determines which path is shortest; if path lengths are equal then we use compareTo of the string method to determine if the
* first path is smaller.
* Determines which path is shortest; if path lengths are equal then we use
* compareTo of the string method to determine if the first path is smaller.
*
* @param left the first path to compare
* @param right the second path to compare
* @return <code>true</code> if the leftPath is the shortest; otherwise <code>false</code>
* @return <code>true</code> if the leftPath is the shortest; otherwise
* <code>false</code>
*/
protected boolean firstPathIsShortest(String left, String right) {
if (left.contains("dctemp")) {
return false;
}
final String leftPath = left.replace('\\', '/');
final String rightPath = right.replace('\\', '/');
@@ -423,6 +499,7 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer implements Anal
* @return true if the path contains '.war\' or '.ear\'.
*/
private boolean containedInWar(String filePath) {
return filePath == null ? false : filePath.matches(".*\\.(ear|war)[\\\\/].*");
return filePath != null && filePath.matches(".*\\.(ear|war)[\\\\/].*");
}
}

View File

@@ -0,0 +1,283 @@
/*
* 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.analyzer;
import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Set;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* This analyzer will merge dependencies, created from different source, into a
* single dependency.</p>
*
* @author Jeremy Long
*/
public class DependencyMergingAnalyzer extends AbstractAnalyzer {
//<editor-fold defaultstate="collapsed" desc="Constants and Member Variables">
/**
* The Logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(DependencyMergingAnalyzer.class);
/**
* a flag indicating if this analyzer has run. This analyzer only runs once.
*/
private boolean analyzed = false;
/**
* Returns a flag indicating if this analyzer has run. This analyzer only
* runs once. Note this is currently only used in the unit tests.
*
* @return a flag indicating if this analyzer has run. This analyzer only
* runs once
*/
protected synchronized boolean getAnalyzed() {
return analyzed;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Dependency Merging Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION;
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Does not support parallel processing as it only runs once and then
* operates on <em>all</em> dependencies.
*
* @return whether or not parallel processing is enabled
* @see #analyze(Dependency, Engine)
*/
@Override
public boolean supportsParallelProcessing() {
return false;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_DEPENDENCY_MERGING_ENABLED;
}
//</editor-fold>
/**
* Analyzes a set of dependencies. If they have been found to be the same
* dependency created by more multiple FileTypeAnalyzers (i.e. a gemspec
* dependency and a dependency from the Bundle Audit Analyzer. The
* dependencies are then merged into a single reportable item.
*
* @param ignore this analyzer ignores the dependency being analyzed
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException {
if (!analyzed) {
analyzed = true;
final Set<Dependency> dependenciesToRemove = new HashSet<>();
final ListIterator<Dependency> mainIterator = engine.getDependencies().listIterator();
//for (Dependency nextDependency : engine.getDependencies()) {
while (mainIterator.hasNext()) {
final Dependency dependency = mainIterator.next();
if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) {
final ListIterator<Dependency> subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex());
while (subIterator.hasNext()) {
final Dependency nextDependency = subIterator.next();
Dependency main;
if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) {
if (main == dependency) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
break; //since we merged into the next dependency - skip forward to the next in mainIterator
}
} else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) {
if (main == dependency) {
mergeDependencies(dependency, nextDependency, dependenciesToRemove);
} else {
mergeDependencies(nextDependency, dependency, dependenciesToRemove);
break; //since we merged into the next dependency - skip forward to the next in mainIterator
}
}
}
}
}
//removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions
// was difficult because of the inner iterator.
engine.getDependencies().removeAll(dependenciesToRemove);
}
}
/**
* Adds the relatedDependency to the dependency's related dependencies.
*
* @param dependency the main dependency
* @param relatedDependency a collection of dependencies to be removed from
* the main analysis loop, this is the source of dependencies to remove
* @param dependenciesToRemove a collection of dependencies that will be
* removed from the main analysis loop, this function adds to this
* collection
*/
private void mergeDependencies(final Dependency dependency, final Dependency relatedDependency, final Set<Dependency> dependenciesToRemove) {
LOGGER.debug("Merging '{}' into '{}'", relatedDependency.getFilePath(), dependency.getFilePath());
dependency.addRelatedDependency(relatedDependency);
dependency.getVendorEvidence().getEvidence().addAll(relatedDependency.getVendorEvidence().getEvidence());
dependency.getProductEvidence().getEvidence().addAll(relatedDependency.getProductEvidence().getEvidence());
dependency.getVersionEvidence().getEvidence().addAll(relatedDependency.getVersionEvidence().getEvidence());
final Iterator<Dependency> i = relatedDependency.getRelatedDependencies().iterator();
while (i.hasNext()) {
dependency.addRelatedDependency(i.next());
i.remove();
}
if (dependency.getSha1sum().equals(relatedDependency.getSha1sum())) {
dependency.addAllProjectReferences(relatedDependency.getProjectReferences());
}
dependenciesToRemove.add(relatedDependency);
}
/**
* Bundling Ruby gems that are identified from different .gemspec files but
* denote the same package path. This happens when Ruby bundler installs an
* application's dependencies by running "bundle install".
*
* @param dependency1 dependency to compare
* @param dependency2 dependency to compare
* @return true if the the dependencies being analyzed appear to be the
* same; otherwise false
*/
private boolean isSameRubyGem(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency2 == null
|| !dependency1.getFileName().endsWith(".gemspec")
|| !dependency2.getFileName().endsWith(".gemspec")
|| dependency1.getPackagePath() == null
|| dependency2.getPackagePath() == null) {
return false;
}
return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath());
}
/**
* Ruby gems installed by "bundle install" can have zero or more *.gemspec
* files, all of which have the same packagePath and should be grouped. If
* one of these gemspec is from <parent>/specifications/*.gemspec, because
* it is a stub with fully resolved gem meta-data created by Ruby bundler,
* this dependency should be the main one. Otherwise, use dependency2 as
* main.
*
* This method returns null if any dependency is not from *.gemspec, or the
* two do not have the same packagePath. In this case, they should not be
* grouped.
*
* @param dependency1 dependency to compare
* @param dependency2 dependency to compare
* @return the main dependency; or null if a gemspec is not included in the
* analysis
*/
private Dependency getMainGemspecDependency(Dependency dependency1, Dependency dependency2) {
if (isSameRubyGem(dependency1, dependency2)) {
final File lFile = dependency1.getActualFile();
final File left = lFile.getParentFile();
if (left != null && left.getName().equalsIgnoreCase("specifications")) {
return dependency1;
}
return dependency2;
}
return null;
}
/**
* Bundling same swift dependencies with the same packagePath but identified
* by different file type analyzers.
*
* @param dependency1 dependency to test
* @param dependency2 dependency to test
* @return <code>true</code> if the dependencies appear to be the same;
* otherwise <code>false</code>
*/
private boolean isSameSwiftPackage(Dependency dependency1, Dependency dependency2) {
if (dependency1 == null || dependency2 == null
|| (!dependency1.getFileName().endsWith(".podspec")
&& !dependency1.getFileName().equals("Package.swift"))
|| (!dependency2.getFileName().endsWith(".podspec")
&& !dependency2.getFileName().equals("Package.swift"))
|| dependency1.getPackagePath() == null
|| dependency2.getPackagePath() == null) {
return false;
}
return dependency1.getPackagePath().equalsIgnoreCase(dependency2.getPackagePath());
}
/**
* Determines which of the swift dependencies should be considered the
* primary.
*
* @param dependency1 the first swift dependency to compare
* @param dependency2 the second swift dependency to compare
* @return the primary swift dependency
*/
private Dependency getMainSwiftDependency(Dependency dependency1, Dependency dependency2) {
if (isSameSwiftPackage(dependency1, dependency2)) {
if (dependency1.getFileName().endsWith(".podspec")) {
return dependency1;
}
return dependency2;
}
return null;
}
}

View File

@@ -13,25 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
* Copyright (c) 2016 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.cpe;
package org.owasp.dependencycheck.analyzer;
import org.junit.Before;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.data.nvdcve.BaseDBTestCase;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An abstract database test case that is used to ensure the H2 DB exists prior to performing tests that utilize the
* data contained within.
* Annotation used to flag an analyzer as experimental.
*
* @author Jeremy Long
* @author jeremy long
*/
public abstract class AbstractDatabaseTestCase extends BaseTest {
@Before
public void setUp() throws Exception {
BaseDBTestCase.ensureDBExists();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Experimental {
}

View File

@@ -34,11 +34,13 @@ import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This analyzer attempts to remove some well known false positives - specifically regarding the java runtime.
* This analyzer attempts to remove some well known false positives -
* specifically regarding the java runtime.
*
* @author Jeremy Long
*/
@@ -69,6 +71,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
@@ -78,20 +81,34 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_FALSE_POSITIVE_ENABLED;
}
//</editor-fold>
/**
* Analyzes the dependencies and removes bad/incorrect CPE associations based on various heuristics.
* Analyzes the dependencies and removes bad/incorrect CPE associations
* based on various heuristics.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
removeJreEntries(dependency);
removeBadMatches(dependency);
removeBadSpringMatches(dependency);
@@ -104,22 +121,23 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
/**
* Removes inaccurate matches on springframework CPEs.
*
* @param dependency the dependency to test for and remove known inaccurate CPE matches
* @param dependency the dependency to test for and remove known inaccurate
* CPE matches
*/
private void removeBadSpringMatches(Dependency dependency) {
String mustContain = null;
for (Identifier i : dependency.getIdentifiers()) {
if ("maven".contains(i.getType())) {
if (i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
final int endPoint = i.getValue().indexOf(":", 19);
if (endPoint >= 0) {
mustContain = i.getValue().substring(19, endPoint).toLowerCase();
break;
}
if ("maven".contains(i.getType())
&& i.getValue() != null && i.getValue().startsWith("org.springframework.")) {
final int endPoint = i.getValue().indexOf(':', 19);
if (endPoint >= 0) {
mustContain = i.getValue().substring(19, endPoint).toLowerCase();
break;
}
}
}
if (mustContain != null) {
if (mustContain
!= null) {
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
@@ -136,7 +154,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
/**
* <p>
* Intended to remove spurious CPE entries. By spurious we mean duplicate, less specific CPE entries.</p>
* Intended to remove spurious CPE entries. By spurious we mean duplicate,
* less specific CPE entries.</p>
* <p>
* Example:</p>
* <code>
@@ -154,8 +173,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*/
@SuppressWarnings("null")
private void removeSpuriousCPE(Dependency dependency) {
final List<Identifier> ids = new ArrayList<Identifier>();
ids.addAll(dependency.getIdentifiers());
final List<Identifier> ids = new ArrayList<>(dependency.getIdentifiers());
Collections.sort(ids);
final ListIterator<Identifier> mainItr = ids.listIterator();
while (mainItr.hasNext()) {
@@ -188,10 +206,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
if (nextVersion.startsWith(currentVersion) || "-".equals(currentVersion)) {
dependency.getIdentifiers().remove(currentId);
}
} else {
if (currentVersion.startsWith(nextVersion) || "-".equals(nextVersion)) {
dependency.getIdentifiers().remove(nextId);
}
} else if (currentVersion.startsWith(nextVersion) || "-".equals(nextVersion)) {
dependency.getIdentifiers().remove(nextId);
}
}
}
@@ -199,7 +215,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
}
/**
* Regex to identify core java libraries and a few other commonly misidentified ones.
* Regex to identify core java libraries and a few other commonly
* misidentified ones.
*/
public static final Pattern CORE_JAVA = Pattern.compile("^cpe:/a:(sun|oracle|ibm):(j2[ems]e|"
+ "java(_platform_micro_edition|_runtime_environment|_se|virtual_machine|se_development_kit|fx)?|"
@@ -214,12 +231,14 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
*/
public static final Pattern CORE_FILES = Pattern.compile("(^|/)((alt[-])?rt|jsse|jfxrt|jfr|jce|javaws|deploy|charsets)\\.jar$");
/**
* Regex to identify core jsf java library files. This is currently incomplete.
* Regex to identify core jsf java library files. This is currently
* incomplete.
*/
public static final Pattern CORE_JSF_FILES = Pattern.compile("(^|/)jsf[-][^/]*\\.jar$");
/**
* Removes any CPE entries for the JDK/JRE unless the filename ends with rt.jar
* Removes any CPE entries for the JDK/JRE unless the filename ends with
* rt.jar
*
* @param dependency the dependency to remove JRE CPEs from
*/
@@ -263,8 +282,9 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
/**
* Removes bad CPE matches for a dependency. Unfortunately, right now these are hard-coded patches for specific problems
* identified when testing this on a LARGE volume of jar files.
* Removes bad CPE matches for a dependency. Unfortunately, right now these
* are hard-coded patches for specific problems identified when testing this
* on a LARGE volume of jar files.
*
* @param dependency the dependency to analyze
*/
@@ -339,7 +359,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
/**
* Removes CPE matches for the wrong version of a dependency. Currently, this only covers Axis 1 & 2.
* Removes CPE matches for the wrong version of a dependency. Currently,
* this only covers Axis 1 & 2.
*
* @param dependency the dependency to analyze
*/
@@ -372,25 +393,25 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
/**
* There are some known CPE entries, specifically regarding sun and oracle products due to the acquisition and changes in
* product names, that based on given evidence we can add the related CPE entries to ensure a complete list of CVE entries.
* There are some known CPE entries, specifically regarding sun and oracle
* products due to the acquisition and changes in product names, that based
* on given evidence we can add the related CPE entries to ensure a complete
* list of CVE entries.
*
* @param dependency the dependency being analyzed
*/
private void addFalseNegativeCPEs(Dependency dependency) {
//TODO move this to the hint analyzer
final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
while (itr.hasNext()) {
final Identifier i = itr.next();
if ("cpe".equals(i.getType()) && i.getValue() != null
&& (i.getValue().startsWith("cpe:/a:oracle:opensso:")
|| i.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
|| i.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
|| i.getValue().startsWith("cpe:/a:sun:opensso:"))) {
final String newCpe = String.format("cpe:/a:sun:opensso_enterprise:%s", i.getValue().substring(22));
final String newCpe2 = String.format("cpe:/a:oracle:opensso_enterprise:%s", i.getValue().substring(22));
final String newCpe3 = String.format("cpe:/a:sun:opensso:%s", i.getValue().substring(22));
final String newCpe4 = String.format("cpe:/a:oracle:opensso:%s", i.getValue().substring(22));
for (final Identifier identifier : dependency.getIdentifiers()) {
if ("cpe".equals(identifier.getType()) && identifier.getValue() != null
&& (identifier.getValue().startsWith("cpe:/a:oracle:opensso:")
|| identifier.getValue().startsWith("cpe:/a:oracle:opensso_enterprise:")
|| identifier.getValue().startsWith("cpe:/a:sun:opensso_enterprise:")
|| identifier.getValue().startsWith("cpe:/a:sun:opensso:"))) {
final String newCpe = String.format("cpe:/a:sun:opensso_enterprise:%s", identifier.getValue().substring(22));
final String newCpe2 = String.format("cpe:/a:oracle:opensso_enterprise:%s", identifier.getValue().substring(22));
final String newCpe3 = String.format("cpe:/a:sun:opensso:%s", identifier.getValue().substring(22));
final String newCpe4 = String.format("cpe:/a:oracle:opensso:%s", identifier.getValue().substring(22));
try {
dependency.addIdentifier("cpe",
newCpe,
@@ -412,19 +433,21 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
/**
* Removes duplicate entries identified that are contained within JAR files. These occasionally crop up due to POM entries or
* other types of files (such as DLLs and EXEs) being contained within the JAR.
* Removes duplicate entries identified that are contained within JAR files.
* These occasionally crop up due to POM entries or other types of files
* (such as DLLs and EXEs) being contained within the JAR.
*
* @param dependency the dependency that might be a duplicate
* @param engine the engine used to scan all dependencies
*/
private void removeDuplicativeEntriesFromJar(Dependency dependency, Engine engine) {
private synchronized void removeDuplicativeEntriesFromJar(Dependency dependency, Engine engine) {
if (dependency.getFileName().toLowerCase().endsWith("pom.xml")
|| DLL_EXE_FILTER.accept(dependency.getActualFile())) {
String parentPath = dependency.getFilePath().toLowerCase();
if (parentPath.contains(".jar")) {
parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4);
final Dependency parent = findDependency(parentPath, engine.getDependencies());
final List<Dependency> dependencies = engine.getDependencies();
final Dependency parent = findDependency(parentPath, dependencies);
if (parent != null) {
boolean remove = false;
for (Identifier i : dependency.getIdentifiers()) {
@@ -441,16 +464,16 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
}
if (remove) {
engine.getDependencies().remove(dependency);
dependencies.remove(dependency);
}
}
}
}
}
/**
* Retrieves a given dependency, based on a given path, from a list of dependencies.
* Retrieves a given dependency, based on a given path, from a list of
* dependencies.
*
* @param dependencyPath the path of the dependency to return
* @param dependencies the collection of dependencies to search
@@ -466,15 +489,16 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
}
/**
* Takes a full CPE and returns the CPE trimmed to include only vendor and product.
* Takes a full CPE and returns the CPE trimmed to include only vendor and
* product.
*
* @param value the CPE value to trim
* @return a CPE value that only includes the vendor and product
*/
private String trimCpeToVendor(String value) {
//cpe:/a:jruby:jruby:1.0.8
final int pos1 = value.indexOf(":", 7); //right of vendor
final int pos2 = value.indexOf(":", pos1 + 1); //right of product
final int pos1 = value.indexOf(':', 7); //right of vendor
final int pos2 = value.indexOf(':', pos1 + 1); //right of product
if (pos2 < 0) {
return value;
} else {

View File

@@ -18,12 +18,16 @@
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.Settings;
/**
*
@@ -31,7 +35,7 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil;
*
* @author Jeremy Long
*/
public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
public class FileNameAnalyzer extends AbstractAnalyzer {
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
@@ -48,6 +52,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
@@ -57,59 +62,70 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_FILE_NAME_ENABLED;
}
//</editor-fold>
/**
* Python init files
*/
//CSOFF: WhitespaceAfter
private static final NameFileFilter IGNORED_FILES = new NameFileFilter(new String[]{
"__init__.py",
"__init__.pyc",
"__init__.pyo",});
//CSON: WhitespaceAfter
/**
* Collects information about the file name.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
//strip any path information that may get added by ArchiveAnalyzer, etc.
final File f = dependency.getActualFile();
String fileName = f.getName();
//remove file extension
final int pos = fileName.lastIndexOf(".");
if (pos > 0) {
fileName = fileName.substring(0, pos);
}
final String fileName = FilenameUtils.removeExtension(f.getName());
//add version evidence
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
if (version != null) {
// If the version number is just a number like 2 or 23, reduce the confidence
// a shade. This should hopefully correct for cases like log4j.jar or
// struts2-core.jar
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
dependency.getVersionEvidence().addEvidence("file", "name",
dependency.getVersionEvidence().addEvidence("file", "version",
version.toString(), Confidence.MEDIUM);
} else {
dependency.getVersionEvidence().addEvidence("file", "name",
dependency.getVersionEvidence().addEvidence("file", "version",
version.toString(), Confidence.HIGHEST);
}
dependency.getVersionEvidence().addEvidence("file", "name",
fileName, Confidence.MEDIUM);
packageName, Confidence.MEDIUM);
}
//add as vendor and product evidence
if (fileName.contains("-")) {
if (!IGNORED_FILES.accept(f)) {
dependency.getProductEvidence().addEvidence("file", "name",
fileName, Confidence.HIGHEST);
packageName, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("file", "name",
fileName, Confidence.HIGHEST);
} else {
dependency.getProductEvidence().addEvidence("file", "name",
fileName, Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("file", "name",
fileName, Confidence.HIGH);
packageName, Confidence.HIGH);
}
}
}

View File

@@ -26,8 +26,4 @@ import java.io.FileFilter;
*/
public interface FileTypeAnalyzer extends Analyzer, FileFilter {
/**
* Resets the analyzers state.
*/
void reset();
}

View File

@@ -17,21 +17,54 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule;
import org.owasp.dependencycheck.xml.hints.HintParseException;
import org.owasp.dependencycheck.xml.hints.HintParser;
import org.owasp.dependencycheck.xml.hints.HintRule;
import org.owasp.dependencycheck.xml.hints.Hints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* This analyzer adds evidence to dependencies to enhance the accuracy of
* library identification.
*
* @author Jeremy Long
*/
public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
public class HintAnalyzer extends AbstractAnalyzer {
/**
* The Logger for use throughout the class
*/
private static final Logger LOGGER = LoggerFactory.getLogger(HintAnalyzer.class);
/**
* The name of the hint rule file
*/
private static final String HINT_RULE_FILE_NAME = "dependencycheck-base-hint.xml";
/**
* The collection of hints.
*/
private Hints hints;
//<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
/**
@@ -62,88 +95,192 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_HINT_ENABLED;
}
/**
* The initialize method does nothing for this Analyzer.
*
* @throws InitializationException thrown if there is an exception
*/
@Override
public void initializeAnalyzer() throws InitializationException {
try {
loadHintRules();
} catch (HintParseException ex) {
LOGGER.debug("Unable to parse hint file", ex);
throw new InitializationException("Unable to parse the hint file", ex);
}
}
//</editor-fold>
/**
* The HintAnalyzer uses knowledge about a dependency to add additional information to help in identification of identifiers
* or vulnerabilities.
* The HintAnalyzer uses knowledge about a dependency to add additional
* information to help in identification of identifiers or vulnerabilities.
*
* @param dependency The dependency being analyzed
* @param engine The scanning engine
* @throws AnalysisException is thrown if there is an exception analyzing the dependency.
* @throws AnalysisException is thrown if there is an exception analyzing
* the dependency.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
final Evidence springTest1 = new Evidence("Manifest",
"Implementation-Title",
"Spring Framework",
Confidence.HIGH);
final Evidence springTest2 = new Evidence("Manifest",
"Implementation-Title",
"org.springframework.core",
Confidence.HIGH);
final Evidence springTest3 = new Evidence("Manifest",
"Implementation-Title",
"spring-core",
Confidence.HIGH);
final Evidence springTest4 = new Evidence("jar",
"package name",
"springframework",
Confidence.LOW);
final Evidence springSecurityTest1 = new Evidence("Manifest",
"Bundle-Name",
"Spring Security Core",
Confidence.MEDIUM);
final Evidence springSecurityTest2 = new Evidence("pom",
"artifactid",
"spring-security-core",
Confidence.HIGH);
//springsource/vware problem
final Set<Evidence> product = dependency.getProductEvidence().getEvidence();
final Set<Evidence> vendor = dependency.getVendorEvidence().getEvidence();
if (product.contains(springTest1) || product.contains(springTest2) || product.contains(springTest3)
|| (dependency.getFileName().contains("spring") && product.contains(springTest4))) {
dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource spring framework", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
for (HintRule hint : hints.getHintRules()) {
boolean matchFound = false;
for (Evidence given : hint.getGivenVendor()) {
if (dependency.getVendorEvidence().getEvidence().contains(given)) {
matchFound = true;
break;
}
}
if (!matchFound) {
for (Evidence given : hint.getGivenProduct()) {
if (dependency.getProductEvidence().getEvidence().contains(given)) {
matchFound = true;
break;
}
}
}
if (!matchFound) {
for (Evidence given : hint.getGivenVersion()) {
if (dependency.getVersionEvidence().getEvidence().contains(given)) {
matchFound = true;
break;
}
}
}
if (!matchFound) {
for (PropertyType pt : hint.getFilenames()) {
if (pt.matches(dependency.getFileName())) {
matchFound = true;
break;
}
}
}
if (matchFound) {
for (Evidence e : hint.getAddVendor()) {
dependency.getVendorEvidence().addEvidence(e);
}
for (Evidence e : hint.getAddProduct()) {
dependency.getProductEvidence().addEvidence(e);
}
for (Evidence e : hint.getAddVersion()) {
dependency.getVersionEvidence().addEvidence(e);
}
for (Evidence e : hint.getRemoveVendor()) {
if (dependency.getVendorEvidence().getEvidence().contains(e)) {
dependency.getVendorEvidence().getEvidence().remove(e);
}
}
for (Evidence e : hint.getRemoveProduct()) {
if (dependency.getProductEvidence().getEvidence().contains(e)) {
dependency.getProductEvidence().getEvidence().remove(e);
}
}
for (Evidence e : hint.getRemoveVersion()) {
if (dependency.getVersionEvidence().getEvidence().contains(e)) {
dependency.getVersionEvidence().getEvidence().remove(e);
}
}
}
}
if (vendor.contains(springTest4)) {
dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_framework", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "pivotal", Confidence.HIGH);
}
if (product.contains(springSecurityTest1) || product.contains(springSecurityTest2)) {
dependency.getProductEvidence().addEvidence("hint analyzer", "product", "springsource_spring_security", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "SpringSource", Confidence.HIGH);
dependency.getVendorEvidence().addEvidence("hint analyzer", "vendor", "vmware", Confidence.HIGH);
}
//sun/oracle problem
final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
final List<Evidence> newEntries = new ArrayList<Evidence>();
final List<Evidence> newEntries = new ArrayList<>();
while (itr.hasNext()) {
final Evidence e = itr.next();
if ("sun".equalsIgnoreCase(e.getValue(false))) {
final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "oracle", e.getConfidence());
newEntries.add(newEvidence);
} else if ("oracle".equalsIgnoreCase(e.getValue(false))) {
final Evidence newEvidence = new Evidence(e.getSource() + " (hint)", e.getName(), "sun", e.getConfidence());
newEntries.add(newEvidence);
for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
newEntries.add(new Evidence(e.getSource() + " (hint)",
e.getName(), dhr.getDuplicate(), e.getConfidence()));
}
}
}
for (Evidence e : newEntries) {
dependency.getVendorEvidence().addEvidence(e);
}
}
/**
* Loads the hint rules file.
*
* @throws HintParseException thrown if the XML cannot be parsed.
*/
private void loadHintRules() throws HintParseException {
final HintParser parser = new HintParser();
File file = null;
try {
hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME));
} catch (HintParseException | SAXException ex) {
LOGGER.error("Unable to parse the base hint data file");
LOGGER.debug("Unable to parse the base hint data file", ex);
}
final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE);
if (filePath == null) {
return;
}
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
if (uriRx.matcher(filePath).matches()) {
deleteTempFile = true;
file = FileUtils.getTempFile("hint", "xml");
final URL url = new URL(filePath);
try {
Downloader.fetchFile(url, file, false);
} catch (DownloadFailedException ex) {
Downloader.fetchFile(url, file, true);
}
} else {
file = new File(filePath);
if (!file.exists()) {
try (InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath)) {
if (fromClasspath != null) {
deleteTempFile = true;
file = FileUtils.getTempFile("hint", "xml");
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
} catch (IOException ex) {
throw new HintParseException("Unable to locate hints file in classpath", ex);
}
}
}
}
}
if (file != null) {
try {
final Hints newHints = parser.parseHints(file);
hints.getHintRules().addAll(newHints.getHintRules());
hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules());
LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size());
LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size());
} catch (HintParseException ex) {
LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
LOGGER.warn(ex.getMessage());
LOGGER.debug("", ex);
throw ex;
}
}
} catch (DownloadFailedException ex) {
throw new HintParseException("Unable to fetch the configured hint file", ex);
} catch (MalformedURLException ex) {
throw new HintParseException("Configured hint file has an invalid URL", ex);
} catch (IOException ex) {
throw new HintParseException("Unable to create temp file for hints", ex);
} finally {
if (deleteTempFile && file != null) {
FileUtils.delete(file);
}
}
}
}

View File

@@ -17,17 +17,16 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@@ -36,18 +35,23 @@ import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.xml.pom.License;
import org.owasp.dependencycheck.xml.pom.PomUtils;
@@ -58,7 +62,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to load a JAR file and collect information that can be used to determine the associated CPE.
* Used to load a JAR file and collect information that can be used to determine
* the associated CPE.
*
* @author Jeremy Long
*/
@@ -70,19 +75,17 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(JarAnalyzer.class);
/**
* The buffer size to use when extracting files from the archive.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static final int BUFFER_SIZE = 4096;
/**
* The count of directories created during analysis. This is used for creating temporary directories.
*/
private static int dirCount = 0;
private static final AtomicInteger DIR_COUNT = new AtomicInteger(0);
/**
* The system independent newline character.
*/
private static final String NEWLINE = System.getProperty("line.separator");
/**
* A list of values in the manifest to ignore as they only result in false positives.
* A list of values in the manifest to ignore as they only result in false
* positives.
*/
private static final Set<String> IGNORE_VALUES = newHashSet(
"Sun Java System Application Server");
@@ -125,7 +128,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
"ipojo-extension",
"eclipse-sourcereferences");
/**
* Deprecated Jar manifest attribute, that is, nonetheless, useful for analysis.
* Deprecated Jar manifest attribute, that is, nonetheless, useful for
* analysis.
*/
@SuppressWarnings("deprecation")
private static final String IMPLEMENTATION_VENDOR_ID = Attributes.Name.IMPLEMENTATION_VENDOR_ID
@@ -146,15 +150,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* A pattern to detect HTML within text.
*/
private static final Pattern HTML_DETECTION_PATTERN = Pattern.compile("\\<[a-z]+.*/?\\>", Pattern.CASE_INSENSITIVE);
//</editor-fold>
/**
* Constructs a new JarAnalyzer.
*/
public JarAnalyzer() {
}
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
/**
* The name of the analyzer.
*/
@@ -173,6 +168,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(EXTENSIONS).build();
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="All standard implmentation details of Analyzer">
/**
* Returns the FileFilter.
*
@@ -198,13 +195,15 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -214,15 +213,16 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Loads a specified JAR file and collects information from the manifest and checksums to identify the correct CPE
* information.
* Loads a specified JAR file and collects information from the manifest and
* checksums to identify the correct CPE information.
*
* @param dependency the dependency to analyze.
* @param engine the engine that is scanning the dependencies
* @throws AnalysisException is thrown if there is an error reading the JAR file.
* @throws AnalysisException is thrown if there is an error reading the JAR
* file.
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
try {
final List<ClassNameInformation> classNames = collectClassNames(dependency);
final String fileName = dependency.getFileName().toLowerCase();
@@ -238,65 +238,58 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final boolean addPackagesAsEvidence = !(hasManifest && hasPOM);
analyzePackageNames(classNames, dependency, addPackagesAsEvidence);
} catch (IOException ex) {
throw new AnalysisException("Exception occurred reading the JAR file.", ex);
throw new AnalysisException("Exception occurred reading the JAR file (" + dependency.getFileName() + ").", ex);
}
}
/**
* Attempts to find a pom.xml within the JAR file. If found it extracts information and adds it to the evidence. This will
* attempt to interpolate the strings contained within the pom.properties if one exists.
* Attempts to find a pom.xml within the JAR file. If found it extracts
* information and adds it to the evidence. This will attempt to interpolate
* the strings contained within the pom.properties if one exists.
*
* @param dependency the dependency being analyzed
* @param classes a collection of class name information
* @param engine the analysis engine, used to add additional dependencies
* @throws AnalysisException is thrown if there is an exception parsing the pom
* @throws AnalysisException is thrown if there is an exception parsing the
* pom
* @return whether or not evidence was added to the dependency
*/
protected boolean analyzePOM(Dependency dependency, List<ClassNameInformation> classes, Engine engine) throws AnalysisException {
boolean foundSomething = false;
final JarFile jar;
try {
jar = new JarFile(dependency.getActualFilePath());
} catch (IOException ex) {
LOGGER.warn("Unable to read JarFile '{}'.", dependency.getActualFilePath());
LOGGER.trace("", ex);
return false;
}
List<String> pomEntries;
try {
pomEntries = retrievePomListing(jar);
} catch (IOException ex) {
LOGGER.warn("Unable to read Jar file entries in '{}'.", dependency.getActualFilePath());
LOGGER.trace("", ex);
return false;
}
File externalPom = null;
if (pomEntries.isEmpty()) {
String pomPath = dependency.getActualFilePath();
pomPath = pomPath.substring(0, pomPath.lastIndexOf('.')) + ".pom";
externalPom = new File(pomPath);
if (externalPom.isFile()) {
pomEntries.add(pomPath);
} else {
return false;
}
}
for (String path : pomEntries) {
LOGGER.debug("Reading pom entry: {}", path);
Properties pomProperties = null;
try {
if (externalPom == null) {
try (JarFile jar = new JarFile(dependency.getActualFilePath())) {
final List<String> pomEntries = retrievePomListing(jar);
if (pomEntries != null && pomEntries.size() <= 1) {
String path;
File pomFile;
Properties pomProperties = null;
if (pomEntries.size() == 1) {
path = pomEntries.get(0);
pomFile = extractPom(path, jar);
pomProperties = retrievePomProperties(path, jar);
} else {
path = FilenameUtils.removeExtension(dependency.getActualFilePath()) + ".pom";
pomFile = new File(path);
}
if (pomFile.isFile()) {
final Model pom = PomUtils.readPom(pomFile);
if (pom != null && pomProperties != null) {
pom.processProperties(pomProperties);
}
return pom != null && setPomEvidence(dependency, pom, classes);
} else {
return false;
}
} catch (IOException ex) {
LOGGER.trace("ignore this, failed reading a non-existent pom.properties", ex);
}
Model pom = null;
try {
if (pomEntries.size() > 1) {
//reported possible null dereference on pomEntries is on a non-feasible path
for (String path : pomEntries) {
//TODO - one of these is likely the pom for the main JAR we are analyzing
LOGGER.debug("Reading pom entry: {}", path);
try {
//extract POM to its own directory and add it as its own dependency
final Dependency newDependency = new Dependency();
pom = extractPom(path, jar, newDependency);
final Properties pomProperties = retrievePomProperties(path, jar);
final File pomFile = extractPom(path, jar);
final Model pom = PomUtils.readPom(pomFile);
pom.processProperties(pomProperties);
final String displayPath = String.format("%s%s%s",
dependency.getFilePath(),
@@ -306,71 +299,60 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
dependency.getFileName(),
File.separator,
path);
final Dependency newDependency = new Dependency();
newDependency.setActualFilePath(pomFile.getAbsolutePath());
newDependency.setFileName(displayName);
newDependency.setFilePath(displayPath);
pom.processProperties(pomProperties);
setPomEvidence(newDependency, pom, null);
engine.getDependencies().add(newDependency);
Collections.sort(engine.getDependencies());
} else {
if (externalPom == null) {
pom = PomUtils.readPom(path, jar);
} else {
pom = PomUtils.readPom(externalPom);
}
pom.processProperties(pomProperties);
foundSomething |= setPomEvidence(dependency, pom, classes);
} catch (AnalysisException ex) {
LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath());
LOGGER.trace("", ex);
}
} catch (AnalysisException ex) {
LOGGER.warn("An error occured while analyzing '{}'.", dependency.getActualFilePath());
LOGGER.trace("", ex);
}
} catch (IOException ex) {
LOGGER.warn("Unable to read JarFile '{}'.", dependency.getActualFilePath());
LOGGER.trace("", ex);
}
return foundSomething;
return false;
}
/**
* Given a path to a pom.xml within a JarFile, this method attempts to load a sibling pom.properties if one exists.
* Given a path to a pom.xml within a JarFile, this method attempts to load
* a sibling pom.properties if one exists.
*
* @param path the path to the pom.xml within the JarFile
* @param jar the JarFile to load the pom.properties from
* @return a Properties object or null if no pom.properties was found
* @throws IOException thrown if there is an exception reading the pom.properties
*/
private Properties retrievePomProperties(String path, final JarFile jar) throws IOException {
private Properties retrievePomProperties(String path, final JarFile jar) {
Properties pomProperties = null;
final String propPath = path.substring(0, path.length() - 7) + "pom.properies";
final ZipEntry propEntry = jar.getEntry(propPath);
if (propEntry != null) {
Reader reader = null;
try {
reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8");
try (Reader reader = new InputStreamReader(jar.getInputStream(propEntry), "UTF-8")) {
pomProperties = new Properties();
pomProperties.load(reader);
LOGGER.debug("Read pom.properties: {}", propPath);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
LOGGER.trace("close error", ex);
}
}
} catch (UnsupportedEncodingException ex) {
LOGGER.trace("UTF-8 is not supported", ex);
} catch (IOException ex) {
LOGGER.trace("Unable to read the POM properties", ex);
}
}
return pomProperties;
}
/**
* Searches a JarFile for pom.xml entries and returns a listing of these entries.
* Searches a JarFile for pom.xml entries and returns a listing of these
* entries.
*
* @param jar the JarFile to search
* @return a list of pom.xml entries
* @throws IOException thrown if there is an exception reading a JarEntry
*/
private List<String> retrievePomListing(final JarFile jar) throws IOException {
final List<String> pomEntries = new ArrayList<String>();
final List<String> pomEntries = new ArrayList<>();
final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
@@ -384,72 +366,29 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Retrieves the specified POM from a jar file and converts it to a Model.
* Retrieves the specified POM from a jar.
*
* @param path the path to the pom.xml file within the jar file
* @param jar the jar file to extract the pom from
* @param dependency the dependency being analyzed
* @return returns the POM object
* @throws AnalysisException is thrown if there is an exception extracting or parsing the POM
* {@link org.owasp.dependencycheck.xml.pom.Model} object
* @return returns the POM file
* @throws AnalysisException is thrown if there is an exception extracting
* the file
*/
private Model extractPom(String path, JarFile jar, Dependency dependency) throws AnalysisException {
InputStream input = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
private File extractPom(String path, JarFile jar) throws AnalysisException {
final File tmpDir = getNextTempDirectory();
final File file = new File(tmpDir, "pom.xml");
try {
final ZipEntry entry = jar.getEntry(path);
input = jar.getInputStream(entry);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);
int count;
final byte[] data = new byte[BUFFER_SIZE];
while ((count = input.read(data, 0, BUFFER_SIZE)) != -1) {
bos.write(data, 0, count);
}
bos.flush();
dependency.setActualFilePath(file.getAbsolutePath());
final ZipEntry entry = jar.getEntry(path);
if (entry == null) {
throw new AnalysisException(String.format("Pom (%s) does not exist in %s", path, jar.getName()));
}
try (InputStream input = jar.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(file)) {
IOUtils.copy(input, fos);
} catch (IOException ex) {
LOGGER.warn("An error occurred reading '{}' from '{}'.", path, dependency.getFilePath());
LOGGER.warn("An error occurred reading '{}' from '{}'.", path, jar.getName());
LOGGER.error("", ex);
} finally {
closeStream(bos);
closeStream(fos);
closeStream(input);
}
return PomUtils.readPom(file);
}
/**
* Silently closes an input stream ignoring errors.
*
* @param stream an input stream to close
*/
private void closeStream(InputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
}
/**
* Silently closes an output stream ignoring errors.
*
* @param stream an output stream to close
*/
private void closeStream(OutputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
return file;
}
/**
@@ -457,16 +396,17 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency to set data on
* @param pom the information from the pom
* @param classes a collection of ClassNameInformation - containing data about the fully qualified class names within the JAR
* file being analyzed
* @return true if there was evidence within the pom that we could use; otherwise false
* @param classes a collection of ClassNameInformation - containing data
* about the fully qualified class names within the JAR file being analyzed
* @return true if there was evidence within the pom that we could use;
* otherwise false
*/
public static boolean setPomEvidence(Dependency dependency, Model pom, List<ClassNameInformation> classes) {
if (pom == null) {
return false;
}
boolean foundSomething = false;
boolean addAsIdentifier = true;
if (pom == null) {
return foundSomething;
}
String groupid = pom.getGroupId();
String parentGroupId = pom.getParentGroupId();
String artifactid = pom.getArtifactId();
@@ -485,7 +425,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
final String originalGroupID = groupid;
if (groupid.startsWith("org.") || groupid.startsWith("com.")) {
if (groupid != null && (groupid.startsWith("org.") || groupid.startsWith("com."))) {
groupid = groupid.substring(4);
}
@@ -494,7 +434,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
final String originalArtifactID = artifactid;
if (artifactid.startsWith("org.") || artifactid.startsWith("com.")) {
if (artifactid != null && (artifactid.startsWith("org.") || artifactid.startsWith("com."))) {
artifactid = artifactid.substring(4);
}
@@ -556,6 +496,12 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classes, org, dependency.getVendorEvidence());
addMatchingValues(classes, org, dependency.getProductEvidence());
}
// org name
final String orgUrl = pom.getOrganizationUrl();
if (orgUrl != null && !orgUrl.isEmpty()) {
dependency.getVendorEvidence().addEvidence("pom", "organization url", orgUrl, Confidence.MEDIUM);
dependency.getProductEvidence().addEvidence("pom", "organization url", orgUrl, Confidence.LOW);
}
//pom name
final String pomName = pom.getName();
if (pomName
@@ -576,22 +522,30 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classes, trimmedDescription, dependency.getProductEvidence());
}
final String projectURL = pom.getProjectURL();
if (projectURL != null && !projectURL.trim().isEmpty()) {
dependency.getVendorEvidence().addEvidence("pom", "url", projectURL, Confidence.HIGHEST);
}
extractLicense(pom, dependency);
return foundSomething;
}
/**
* Analyzes the path information of the classes contained within the JarAnalyzer to try and determine possible vendor or
* product names. If any are found they are stored in the packageVendor and packageProduct hashSets.
* Analyzes the path information of the classes contained within the
* JarAnalyzer to try and determine possible vendor or product names. If any
* are found they are stored in the packageVendor and packageProduct
* hashSets.
*
* @param classNames a list of class names
* @param dependency a dependency to analyze
* @param addPackagesAsEvidence a flag indicating whether or not package names should be added as evidence.
* @param addPackagesAsEvidence a flag indicating whether or not package
* names should be added as evidence.
*/
protected void analyzePackageNames(List<ClassNameInformation> classNames,
Dependency dependency, boolean addPackagesAsEvidence) {
final Map<String, Integer> vendorIdentifiers = new HashMap<String, Integer>();
final Map<String, Integer> productIdentifiers = new HashMap<String, Integer>();
final Map<String, Integer> vendorIdentifiers = new HashMap<>();
final Map<String, Integer> productIdentifiers = new HashMap<>();
analyzeFullyQualifiedClassNames(classNames, vendorIdentifiers, productIdentifiers);
final int classCount = classNames.size();
@@ -621,11 +575,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* <p>
* Reads the manifest from the JAR file and collects the entries. Some vendorKey entries are:</p>
* Reads the manifest from the JAR file and collects the entries. Some
* vendorKey entries are:</p>
* <ul><li>Implementation Title</li>
* <li>Implementation Version</li> <li>Implementation Vendor</li>
* <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle Version</li> <li>Bundle Vendor</li> <li>Bundle
* Description</li> <li>Main Class</li> </ul>
* <li>Implementation VendorId</li> <li>Bundle Name</li> <li>Bundle
* Version</li> <li>Bundle Vendor</li> <li>Bundle Description</li> <li>Main
* Class</li> </ul>
* However, all but a handful of specific entries are read in.
*
* @param dependency A reference to the dependency
@@ -633,16 +589,12 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @return whether evidence was identified parsing the manifest
* @throws IOException if there is an issue reading the JAR file
*/
protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException {
protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation)
throws IOException {
boolean foundSomething = false;
JarFile jar = null;
try {
jar = new JarFile(dependency.getActualFilePath());
try (JarFile jar = new JarFile(dependency.getActualFilePath())) {
final Manifest manifest = jar.getManifest();
if (manifest == null) {
//don't log this for javadoc or sources jar files
if (!dependency.getFileName().toLowerCase().endsWith("-sources.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-javadoc.jar")
&& !dependency.getFileName().toLowerCase().endsWith("-src.jar")
@@ -652,17 +604,13 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
return false;
}
final Attributes atts = manifest.getMainAttributes();
final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
final EvidenceCollection productEvidence = dependency.getProductEvidence();
final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
final String source = "Manifest";
String source = "Manifest";
String specificationVersion = null;
boolean hasImplementationVersion = false;
Attributes atts = manifest.getMainAttributes();
for (Entry<Object, Object> entry : atts.entrySet()) {
String key = entry.getKey().toString();
String value = atts.getValue(key);
@@ -680,7 +628,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
foundSomething = true;
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
} else if ("specification-version".equalsIgnoreCase(key)) {
specificationVersion = key;
specificationVersion = value;
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
foundSomething = true;
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
@@ -692,7 +640,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
} else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
foundSomething = true;
addDescription(dependency, value, "manifest", key);
//productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
foundSomething = true;
@@ -700,25 +647,14 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classInformation, value, productEvidence);
// //the following caused false positives.
// } else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
// foundSomething = true;
// vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
// addMatchingValues(classInformation, value, vendorEvidence);
} else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
foundSomething = true;
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
continue;
//skipping main class as if this has important information to add
// it will be added during class name analysis... if other fields
// have the information from the class name then they will get added...
// foundSomething = true;
// productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
// vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
// addMatchingValues(classInformation, value, vendorEvidence);
// addMatchingValues(classInformation, value, productEvidence);
//skipping main class as if this has important information to add it will be added during class name analysis...
} else {
key = key.toLowerCase();
if (!IGNORE_KEYS.contains(key)
&& !key.endsWith("jdk")
&& !key.contains("lastmodified")
@@ -730,21 +666,18 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
&& !value.trim().startsWith("scm:")
&& !isImportPackage(key, value)
&& !isPackage(key, value)) {
foundSomething = true;
if (key.contains("version")) {
if (!key.contains("specification")) {
//versionEvidence.addEvidence(source, key, value, Confidence.LOW);
//} else {
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
}
} else if ("build-id".equals(key)) {
int pos = value.indexOf('(');
if (pos >= 0) {
if (pos > 0) {
value = value.substring(0, pos - 1);
}
pos = value.indexOf('[');
if (pos >= 0) {
if (pos > 0) {
value = value.substring(0, pos - 1);
}
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
@@ -765,21 +698,19 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
addMatchingValues(classInformation, value, productEvidence);
} else if (key.contains("license")) {
addLicense(dependency, value);
} else if (key.contains("description")) {
addDescription(dependency, value, "manifest", key);
} else {
if (key.contains("description")) {
addDescription(dependency, value, "manifest", key);
} else {
productEvidence.addEvidence(source, key, value, Confidence.LOW);
vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
addMatchingValues(classInformation, value, vendorEvidence);
addMatchingValues(classInformation, value, productEvidence);
if (value.matches(".*\\d.*")) {
final StringTokenizer tokenizer = new StringTokenizer(value, " ");
while (tokenizer.hasMoreElements()) {
final String s = tokenizer.nextToken();
if (s.matches("^[0-9.]+$")) {
versionEvidence.addEvidence(source, key, s, Confidence.LOW);
}
productEvidence.addEvidence(source, key, value, Confidence.LOW);
vendorEvidence.addEvidence(source, key, value, Confidence.LOW);
addMatchingValues(classInformation, value, vendorEvidence);
addMatchingValues(classInformation, value, productEvidence);
if (value.matches(".*\\d.*")) {
final StringTokenizer tokenizer = new StringTokenizer(value, " ");
while (tokenizer.hasMoreElements()) {
final String s = tokenizer.nextToken();
if (s.matches("^[0-9.]+$")) {
versionEvidence.addEvidence(source, key, s, Confidence.LOW);
}
}
}
@@ -787,28 +718,52 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
}
}
for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) {
final String name = item.getKey();
source = "manifest: " + name;
atts = item.getValue();
for (Entry<Object, Object> entry : atts.entrySet()) {
final String key = entry.getKey().toString();
final String value = atts.getValue(key);
if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
foundSomething = true;
productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
foundSomething = true;
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
foundSomething = true;
vendorEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, vendorEvidence);
} else if (key.equalsIgnoreCase(Attributes.Name.SPECIFICATION_TITLE.toString())) {
foundSomething = true;
productEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
}
}
}
if (specificationVersion != null && !hasImplementationVersion) {
foundSomething = true;
versionEvidence.addEvidence(source, "specificationn-version", specificationVersion, Confidence.HIGH);
}
} finally {
if (jar != null) {
jar.close();
versionEvidence.addEvidence(source, "specification-version", specificationVersion, Confidence.HIGH);
}
}
return foundSomething;
}
/**
* Adds a description to the given dependency. If the description contains one of the following strings beyond 100 characters,
* then the description used will be trimmed to that position:
* <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses "</li></ul>
* Adds a description to the given dependency. If the description contains
* one of the following strings beyond 100 characters, then the description
* used will be trimmed to that position:
* <ul><li>"such as"</li><li>"like "</li><li>"will use "</li><li>"* uses
* "</li></ul>
*
* @param dependency a dependency
* @param description the description
* @param source the source of the evidence
* @param key the "name" of the evidence
* @return if the description is trimmed, the trimmed version is returned; otherwise the original description is returned
* @return if the description is trimmed, the trimmed version is returned;
* otherwise the original description is returned
*/
public static String addDescription(Dependency dependency, String description, String source, String key) {
if (dependency.getDescription() == null) {
@@ -846,10 +801,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
if (pos > 0) {
final StringBuilder sb = new StringBuilder(pos + 3);
sb.append(desc.substring(0, pos));
sb.append("...");
desc = sb.toString();
desc = desc.substring(0, pos) + "...";
}
dependency.getProductEvidence().addEvidence(source, key, desc, Confidence.LOW);
dependency.getVendorEvidence().addEvidence(source, key, desc, Confidence.LOW);
@@ -882,19 +834,27 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the JarAnalyzer.
*
* @throws Exception is thrown if there is an exception creating a temporary directory
* @throws InitializationException is thrown if there is an exception
* creating a temporary directory
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
setEnabled(false);
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
setEnabled(false);
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}
@@ -902,22 +862,27 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* Deletes any files extracted from the JAR during analysis.
*/
@Override
public void close() {
public void closeAnalyzer() {
if (tempFileLocation != null && tempFileLocation.exists()) {
LOGGER.debug("Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success) {
LOGGER.warn("Failed to delete some temporary files, see the log for more details");
if (!success && tempFileLocation.exists()) {
final String[] l = tempFileLocation.list();
if (l != null && l.length > 0) {
LOGGER.warn("Failed to delete some temporary files, see the log for more details");
}
}
}
}
/**
* Determines if the key value pair from the manifest is for an "import" type entry for package names.
* Determines if the key value pair from the manifest is for an "import"
* type entry for package names.
*
* @param key the key from the manifest
* @param value the value from the manifest
* @return true or false depending on if it is believed the entry is an "import" entry
* @return true or false depending on if it is believed the entry is an
* "import" entry
*/
private boolean isImportPackage(String key, String value) {
final Pattern packageRx = Pattern.compile("^([a-zA-Z0-9_#\\$\\*\\.]+\\s*[,;]\\s*)+([a-zA-Z0-9_#\\$\\*\\.]+\\s*)?$");
@@ -926,17 +891,16 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Cycles through an enumeration of JarEntries, contained within the dependency, and returns a list of the class names. This
* does not include core Java package names (i.e. java.* or javax.*).
* Cycles through an enumeration of JarEntries, contained within the
* dependency, and returns a list of the class names. This does not include
* core Java package names (i.e. java.* or javax.*).
*
* @param dependency the dependency being analyzed
* @return an list of fully qualified class names
*/
private List<ClassNameInformation> collectClassNames(Dependency dependency) {
final List<ClassNameInformation> classNames = new ArrayList<ClassNameInformation>();
JarFile jar = null;
try {
jar = new JarFile(dependency.getActualFilePath());
final List<ClassNameInformation> classNames = new ArrayList<>();
try (JarFile jar = new JarFile(dependency.getActualFilePath())) {
final Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
@@ -950,25 +914,21 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
} catch (IOException ex) {
LOGGER.warn("Unable to open jar file '{}'.", dependency.getFileName());
LOGGER.debug("", ex);
} finally {
if (jar != null) {
try {
jar.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
}
return classNames;
}
/**
* Cycles through the list of class names and places the package levels 0-3 into the provided maps for vendor and product.
* This is helpful when analyzing vendor/product as many times this is included in the package name.
* Cycles through the list of class names and places the package levels 0-3
* into the provided maps for vendor and product. This is helpful when
* analyzing vendor/product as many times this is included in the package
* name.
*
* @param classNames a list of class names
* @param vendor HashMap of possible vendor names from package names (e.g. owasp)
* @param product HashMap of possible product names from package names (e.g. dependencycheck)
* @param vendor HashMap of possible vendor names from package names (e.g.
* owasp)
* @param product HashMap of possible product names from package names (e.g.
* dependencycheck)
*/
private void analyzeFullyQualifiedClassNames(List<ClassNameInformation> classNames,
Map<String, Integer> vendor, Map<String, Integer> product) {
@@ -978,13 +938,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
if (list.size() == 2) {
addEntry(product, list.get(1));
}
if (list.size() == 3) {
} else if (list.size() == 3) {
addEntry(vendor, list.get(1));
addEntry(product, list.get(1));
addEntry(product, list.get(2));
}
if (list.size() >= 4) {
} else if (list.size() >= 4) {
addEntry(vendor, list.get(1));
addEntry(vendor, list.get(2));
addEntry(product, list.get(1));
@@ -995,8 +953,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Adds an entry to the specified collection and sets the Integer (e.g. the count) to 1. If the entry already exists in the
* collection then the Integer is incremented by 1.
* Adds an entry to the specified collection and sets the Integer (e.g. the
* count) to 1. If the entry already exists in the collection then the
* Integer is incremented by 1.
*
* @param collection a collection of strings and their occurrence count
* @param key the key to add to the collection
@@ -1010,9 +969,10 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Cycles through the collection of class name information to see if parts of the package names are contained in the provided
* value. If found, it will be added as the HIGHEST confidence evidence because we have more then one source corroborating the
* value.
* Cycles through the collection of class name information to see if parts
* of the package names are contained in the provided value. If found, it
* will be added as the HIGHEST confidence evidence because we have more
* then one source corroborating the value.
*
* @param classes a collection of class name information
* @param value the value to check to see if it contains a package name
@@ -1025,7 +985,9 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
final String text = value.toLowerCase();
for (ClassNameInformation cni : classes) {
for (String key : cni.getPackageStructure()) {
if (text.contains(key)) { //note, package structure elements are already lowercase.
final Pattern p = Pattern.compile("\b" + key + "\b");
if (p.matcher(text).find()) {
//if (text.contains(key)) { //note, package structure elements are already lowercase.
evidence.addEvidence("jar", "package name", key, Confidence.HIGHEST);
}
}
@@ -1033,7 +995,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Simple check to see if the attribute from a manifest is just a package name.
* Simple check to see if the attribute from a manifest is just a package
* name.
*
* @param key the key of the value to check
* @param value the value to check
@@ -1047,7 +1010,8 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Extracts the license information from the pom and adds it to the dependency.
* Extracts the license information from the pom and adds it to the
* dependency.
*
* @param pom the pom object
* @param dependency the dependency to add license information too
@@ -1092,12 +1056,24 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
*/
protected static class ClassNameInformation {
/**
* The fully qualified class name.
*/
private String name;
/**
* Up to the first four levels of the package structure, excluding a
* leading "org" or "com".
*/
private final ArrayList<String> packageStructure = new ArrayList<>();
/**
* <p>
* Stores information about a given class name. This class will keep the fully qualified class name and a list of the
* important parts of the package structure. Up to the first four levels of the package structure are stored, excluding a
* leading "org" or "com". Example:</p>
* <code>ClassNameInformation obj = new ClassNameInformation("org.owasp.dependencycheck.analyzer.JarAnalyzer");
* Stores information about a given class name. This class will keep the
* fully qualified class name and a list of the important parts of the
* package structure. Up to the first four levels of the package
* structure are stored, excluding a leading "org" or "com".
* Example:</p>
* <code>ClassNameInformation obj = new ClassNameInformation("org/owasp/dependencycheck/analyzer/JarAnalyzer");
* System.out.println(obj.getName());
* for (String p : obj.getPackageStructure())
* System.out.println(p);
@@ -1115,7 +1091,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
ClassNameInformation(String className) {
name = className;
if (name.contains("/")) {
final String[] tmp = className.toLowerCase().split("/");
final String[] tmp = StringUtils.split(className.toLowerCase(), '/');
int start = 0;
int end = 3;
if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
@@ -1125,17 +1101,11 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
if (tmp.length <= end) {
end = tmp.length - 1;
}
for (int i = start; i <= end; i++) {
packageStructure.add(tmp[i]);
}
packageStructure.addAll(Arrays.asList(tmp).subList(start, end + 1));
} else {
packageStructure.add(name);
}
}
/**
* The fully qualified class name.
*/
private String name;
/**
* Get the value of name
@@ -1154,10 +1124,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
public void setName(String name) {
this.name = name;
}
/**
* Up to the first four levels of the package structure, excluding a leading "org" or "com".
*/
private final ArrayList<String> packageStructure = new ArrayList<String>();
/**
* Get the value of packageStructure
@@ -1176,7 +1142,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException thrown if unable to create temporary directory
*/
private File getNextTempDirectory() throws AnalysisException {
dirCount += 1;
final int dirCount = DIR_COUNT.incrementAndGet();
final File directory = new File(tempFileLocation, String.valueOf(dirCount));
//getting an exception for some directories not being able to be created; might be because the directory already exists?
if (directory.exists()) {

View File

@@ -35,6 +35,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
@@ -42,15 +43,18 @@ import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will attempt to locate a dependency on a Nexus service by SHA-1 digest of the dependency.
* Analyzer which will attempt to locate a dependency on a Nexus service by
* SHA-1 digest of the dependency.
*
* There are two settings which govern this behavior:
*
* <ul>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_ENABLED} determines whether this analyzer is even
* enabled. This can be overridden by setting the system property.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_URL} the URL to a Nexus service to search by SHA-1.
* There is an expected <code>%s</code> in this where the SHA-1 will get entered.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_ENABLED}
* determines whether this analyzer is even enabled. This can be overridden by
* setting the system property.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_URL}
* the URL to a Nexus service to search by SHA-1. There is an expected
* <code>%s</code> in this where the SHA-1 will get entered.</li>
* </ul>
*
* @author colezlaw
@@ -58,7 +62,8 @@ import org.owasp.dependencycheck.utils.Settings;
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The default URL - this will be used by the CentralAnalyzer to determine whether to enable this.
* The default URL - this will be used by the CentralAnalyzer to determine
* whether to enable this.
*/
public static final String DEFAULT_URL = "https://repository.sonatype.org/service/local/";
@@ -95,7 +100,8 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Determines if this analyzer is enabled
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
* @return <code>true</code> if the analyzer is enabled; otherwise
* <code>false</code>
*/
private boolean checkEnabled() {
/* Enable this analyzer ONLY if the Nexus URL has been set to something
@@ -104,7 +110,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
*/
boolean retval = false;
try {
if ((!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL)))
if (!DEFAULT_URL.equals(Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL))
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED)) {
LOGGER.info("Enabling Nexus analyzer");
retval = true;
@@ -131,26 +137,25 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
LOGGER.debug("Initializing Nexus Analyzer");
LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled());
if (isEnabled()) {
final boolean useProxy = useProxy();
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
LOGGER.debug("Nexus Analyzer URL: {}", searchUrl);
try {
searcher = new NexusSearch(new URL(searchUrl));
searcher = new NexusSearch(new URL(searchUrl), useProxy);
if (!searcher.preflightRequest()) {
LOGGER.warn("There was an issue getting Nexus status. Disabling analyzer.");
setEnabled(false);
throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
}
} catch (MalformedURLException mue) {
// I know that initialize can throw an exception, but we'll
// just disable the analyzer if the URL isn't valid
LOGGER.warn("Property {} not a valid URL. Nexus Analyzer disabled", searchUrl);
setEnabled(false);
throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue);
}
}
}
@@ -166,7 +171,8 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -208,7 +214,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
if (!isEnabled()) {
return;
}
@@ -240,14 +246,15 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.warn("Unable to download pom.xml for {} from Nexus repository; "
+ "this could result in undetected CPE/CVEs.", dependency.getFileName());
} finally {
if (pomFile != null && !FileUtils.deleteQuietly(pomFile)) {
if (pomFile != null && pomFile.exists() && !FileUtils.deleteQuietly(pomFile)) {
LOGGER.debug("Failed to delete temporary pom file {}", pomFile.toString());
pomFile.deleteOnExit();
}
}
}
} catch (IllegalArgumentException iae) {
//dependency.addAnalysisException(new AnalysisException("Invalid SHA-1"));
LOGGER.info(String.format("invalid sha-1 hash on %s", dependency.getFileName()));
LOGGER.info("invalid sha-1 hash on {}", dependency.getFileName());
} catch (FileNotFoundException fnfe) {
//dependency.addAnalysisException(new AnalysisException("Artifact not found on repository"));
LOGGER.debug("Artifact not found in repository '{}'", dependency.getFileName());
@@ -257,4 +264,19 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.debug("Could not connect to nexus repository", ioe);
}
}
/**
* Determine if a proxy should be used.
*
* @return {@code true} if a proxy should be used
*/
public static boolean useProxy() {
try {
return Settings.getString(Settings.KEYS.PROXY_SERVER) != null
&& Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY);
} catch (InvalidSettingException ise) {
LOGGER.warn("Failed to parse proxy settings.", ise);
return false;
}
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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) 2015 Institute for Defense Analyses. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Map;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonValue;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Node Package Manager (npm) package.json files, and collect
* information that can be used to determine the associated CPE.
*
* @author Dale Visser
*/
@Experimental
public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(NodePackageAnalyzer.class);
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Node.js Package Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The file name to scan.
*/
public static final String PACKAGE_JSON = "package.json";
/**
* Filter that detects files named "package.json".
*/
private static final FileFilter PACKAGE_JSON_FILTER = FileFilterBuilder.newInstance()
.addFilenames(PACKAGE_JSON).build();
/**
* Returns the FileFilter
*
* @return the FileFilter
*/
@Override
protected FileFilter getFileFilter() {
return PACKAGE_JSON_FILTER;
}
@Override
protected void initializeFileTypeAnalyzer() throws InitializationException {
// NO-OP
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED;
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
final File file = dependency.getActualFile();
try (JsonReader jsonReader = Json.createReader(FileUtils.openInputStream(file))) {
final JsonObject json = jsonReader.readObject();
final EvidenceCollection productEvidence = dependency.getProductEvidence();
final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
if (json.containsKey("name")) {
final Object value = json.get("name");
if (value instanceof JsonString) {
final String valueString = ((JsonString) value).getString();
productEvidence.addEvidence(PACKAGE_JSON, "name", valueString, Confidence.HIGHEST);
vendorEvidence.addEvidence(PACKAGE_JSON, "name_project", String.format("%s_project", valueString), Confidence.LOW);
} else {
LOGGER.warn("JSON value not string as expected: {}", value);
}
}
addToEvidence(json, productEvidence, "description");
addToEvidence(json, vendorEvidence, "author");
addToEvidence(json, dependency.getVersionEvidence(), "version");
dependency.setDisplayFileName(String.format("%s/%s", file.getParentFile().getName(), file.getName()));
} catch (JsonException e) {
LOGGER.warn("Failed to parse package.json file.", e);
} catch (IOException e) {
throw new AnalysisException("Problem occurred while reading dependency file.", e);
}
}
/**
* Adds information to an evidence collection from the node json
* configuration.
*
* @param json information from node.js
* @param collection a set of evidence about a dependency
* @param key the key to obtain the data from the json information
*/
private void addToEvidence(JsonObject json, EvidenceCollection collection, String key) {
if (json.containsKey(key)) {
final JsonValue value = json.get(key);
if (value instanceof JsonString) {
collection.addEvidence(PACKAGE_JSON, key, ((JsonString) value).getString(), Confidence.HIGHEST);
} else if (value instanceof JsonObject) {
final JsonObject jsonObject = (JsonObject) value;
for (final Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
final String property = entry.getKey();
final JsonValue subValue = entry.getValue();
if (subValue instanceof JsonString) {
collection.addEvidence(PACKAGE_JSON,
String.format("%s.%s", key, property),
((JsonString) subValue).getString(),
Confidence.HIGHEST);
} else {
LOGGER.warn("JSON sub-value not string as expected: {}", subValue);
}
}
} else {
LOGGER.warn("JSON value not string or JSON object as expected: {}", value);
}
}
}
}

View File

@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Analyzer which will parse a Nuspec file to gather module information.
@@ -65,10 +65,10 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
}
/**
@@ -82,7 +82,8 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -125,27 +126,15 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
* @throws AnalysisException when there's an exception during analysis
*/
@Override
public void analyzeFileType(Dependency dependency, Engine engine) throws AnalysisException {
LOGGER.debug("Checking Nuspec file {}", dependency.toString());
public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
LOGGER.debug("Checking Nuspec file {}", dependency);
try {
final NuspecParser parser = new XPathNuspecParser();
NugetPackage np = null;
FileInputStream fis = null;
try {
fis = new FileInputStream(dependency.getActualFilePath());
try (FileInputStream fis = new FileInputStream(dependency.getActualFilePath())) {
np = parser.parse(fis);
} catch (NuspecParseException ex) {
} catch (NuspecParseException | FileNotFoundException ex) {
throw new AnalysisException(ex);
} catch (FileNotFoundException ex) {
throw new AnalysisException(ex);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
LOGGER.debug("Error closing input stream");
}
}
}
if (np.getOwners() != null) {

View File

@@ -27,19 +27,24 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.LoggerFactory;
/**
* NvdCveAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated
* CVEs. It uses the the identifiers found by other analyzers to lookup the CVE data.
* NvdCveAnalyzer is a utility class that takes a project dependency and
* attempts to discern if there is an associated CVEs. It uses the the
* identifiers found by other analyzers to lookup the CVE data.
*
* @author Jeremy Long
*/
public class NvdCveAnalyzer implements Analyzer {
public class NvdCveAnalyzer extends AbstractAnalyzer {
/**
* The maximum number of query results to return.
* The Logger for use throughout the class
*/
static final int MAX_QUERY_RESULTS = 100;
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class);
/**
* The CVE Index.
*/
@@ -51,18 +56,18 @@ public class NvdCveAnalyzer implements Analyzer {
* @throws SQLException thrown when there is a SQL Exception
* @throws IOException thrown when there is an IO Exception
* @throws DatabaseException thrown when there is a database exceptions
* @throws ClassNotFoundException thrown if the h2 database driver cannot be loaded
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
* loaded
*/
public void open() throws SQLException, IOException, DatabaseException, ClassNotFoundException {
cveDB = new CveDB();
cveDB.open();
cveDB = CveDB.getInstance();
}
/**
* Closes the data source.
*/
@Override
public void close() {
public void closeAnalyzer() {
cveDB.close();
cveDB = null;
}
@@ -73,31 +78,20 @@ public class NvdCveAnalyzer implements Analyzer {
* @return true or false.
*/
public boolean isOpen() {
return (cveDB != null);
return cveDB != null;
}
/**
* Ensures that the CVE Database is closed.
*
* @throws Throwable when a throwable is thrown.
*/
@Override
protected void finalize() throws Throwable {
super.finalize();
if (isOpen()) {
close();
}
}
/**
* Analyzes a dependency and attempts to determine if there are any CPE identifiers for this dependency.
* Analyzes a dependency and attempts to determine if there are any CPE
* identifiers for this dependency.
*
* @param dependency The Dependency to analyze
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the dependency
* @throws AnalysisException thrown if there is an issue analyzing the
* dependency
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
for (Identifier id : dependency.getIdentifiers()) {
if ("cpe".equals(id.getType())) {
try {
@@ -143,12 +137,38 @@ public class NvdCveAnalyzer implements Analyzer {
}
/**
* Opens the database used to gather NVD CVE data.
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @throws Exception is thrown if there is an issue opening the index.
* @return the key for the analyzer's enabled property
*/
@Override
public void initialize() throws Exception {
this.open();
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_NVD_CVE_ENABLED;
}
/**
* Opens the database used to gather NVD CVE data.
*
* @throws InitializationException is thrown if there is an issue opening
* the index.
*/
@Override
public void initializeAnalyzer() throws InitializationException {
try {
this.open();
} catch (SQLException ex) {
LOGGER.debug("SQL Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (IOException ex) {
LOGGER.debug("IO Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (DatabaseException ex) {
LOGGER.debug("Database Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (ClassNotFoundException ex) {
LOGGER.debug("Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
}
}
}

View File

@@ -28,16 +28,21 @@ import org.owasp.dependencycheck.utils.Settings;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze OpenSSL source code present in the file system.
*
* @author Dale Visser <dvisser@ida.org>
* @author Dale Visser
*/
public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Hexadecimal.
*/
private static final int HEXADECIMAL = 16;
/**
* Filename to analyze. All other .h files get removed from consideration.
@@ -48,17 +53,47 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
* Filter that detects files named "__init__.py".
*/
private static final FileFilter OPENSSLV_FILTER = FileFilterBuilder.newInstance().addFilenames(OPENSSLV_H).build();
/**
* Open SSL Version number pattern.
*/
private static final Pattern VERSION_PATTERN = Pattern.compile(
"define\\s+OPENSSL_VERSION_NUMBER\\s+0x([0-9a-zA-Z]{8})L", Pattern.DOTALL
| Pattern.CASE_INSENSITIVE);
/**
* The offset of the major version number.
*/
private static final int MAJOR_OFFSET = 28;
/**
* The mask for the minor version number.
*/
private static final long MINOR_MASK = 0x0ff00000L;
/**
* The offset of the minor version number.
*/
private static final int MINOR_OFFSET = 20;
/**
* The max for the fix version.
*/
private static final long FIX_MASK = 0x000ff000L;
/**
* The offset for the fix version.
*/
private static final int FIX_OFFSET = 12;
/**
* The mask for the patch version.
*/
private static final long PATCH_MASK = 0x00000ff0L;
/**
* The offset for the patch version.
*/
private static final int PATCH_OFFSET = 4;
/**
* Number of letters.
*/
private static final int NUM_LETTERS = 26;
/**
* The status mask.
*/
private static final int STATUS_MASK = 0x0000000f;
/**
@@ -67,7 +102,7 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
* @param openSSLVersionConstant The open SSL version
* @return the version of openssl
*/
static String getOpenSSLVersion(long openSSLVersionConstant) {
protected static String getOpenSSLVersion(long openSSLVersionConstant) {
final long major = openSSLVersionConstant >>> MAJOR_OFFSET;
final long minor = (openSSLVersionConstant & MINOR_MASK) >>> MINOR_OFFSET;
final long fix = (openSSLVersionConstant & FIX_MASK) >>> FIX_OFFSET;
@@ -111,10 +146,10 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
/**
* No-op initializer implementation.
*
* @throws Exception never thrown
* @throws InitializationException never thrown
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// Nothing to do here.
}
@@ -123,10 +158,11 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File file = dependency.getActualFile();
final String parentName = file.getParentFile().getName();
@@ -158,16 +194,19 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
*/
private String getFileContents(final File actualFile)
throws AnalysisException {
String contents;
try {
contents = FileUtils.readFileToString(actualFile).trim();
return FileUtils.readFileToString(actualFile, Charset.defaultCharset()).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
}
return contents;
}
/**
* Returns the setting for the analyzer enabled setting key.
*
* @return the setting for the analyzer enabled setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_OPENSSL_ENABLED;

View File

@@ -23,10 +23,11 @@ import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.io.input.AutoCloseInputStream;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.StringUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
@@ -37,23 +38,27 @@ import org.slf4j.LoggerFactory;
import javax.mail.MessagingException;
import javax.mail.internet.InternetHeaders;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.ExtractionException;
import org.owasp.dependencycheck.utils.ExtractionUtil;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Used to analyze a Wheel or egg distribution files, or their contents in unzipped form, and collect information that can be used
* to determine the associated CPE.
* Used to analyze a Wheel or egg distribution files, or their contents in
* unzipped form, and collect information that can be used to determine the
* associated CPE.
*
* @author Dale Visser <dvisser@ida.org>
* @author Dale Visser
*/
@Experimental
public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Name of egg metatdata files to analyze.
* Name of egg metadata files to analyze.
*/
private static final String PKG_INFO = "PKG-INFO";
@@ -69,9 +74,10 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
.getLogger(PythonDistributionAnalyzer.class);
/**
* The count of directories created during analysis. This is used for creating temporary directories.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static int dirCount = 0;
private static final AtomicInteger DIR_COUNT = new AtomicInteger(0);
/**
* The name of the analyzer.
@@ -103,7 +109,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
private File tempFileLocation;
/**
* Filter that detects *.dist-info files (but doesn't verify they are directories.
* Filter that detects *.dist-info files (but doesn't verify they are
* directories.
*/
private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(
".dist-info");
@@ -163,7 +170,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -173,7 +181,7 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File actualFile = dependency.getActualFile();
if (WHL_FILTER.accept(actualFile)) {
@@ -205,7 +213,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
* @param dependency the archive being scanned
* @param folderFilter the filter to apply to the folder
* @param metadataFilter the filter to apply to the meta data
* @throws AnalysisException thrown when there is a problem analyzing the dependency
* @throws AnalysisException thrown when there is a problem analyzing the
* dependency
*/
private void collectMetadataFromArchiveFormat(Dependency dependency,
FilenameFilter folderFilter, FilenameFilter metadataFilter)
@@ -220,32 +229,43 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
throw new AnalysisException(ex);
}
collectWheelMetadata(
dependency,
getMatchingFile(getMatchingFile(temp, folderFilter),
metadataFilter));
File matchingFile = getMatchingFile(temp, folderFilter);
if (matchingFile != null) {
matchingFile = getMatchingFile(matchingFile, metadataFilter);
if (matchingFile != null) {
collectWheelMetadata(dependency, matchingFile);
}
}
}
/**
* Makes sure a usable temporary directory is available.
*
* @throws Exception an AnalyzeException is thrown when the temp directory cannot be created
* @throws InitializationException an AnalyzeException is thrown when the
* temp directory cannot be created
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format(
"Unable to delete temporary file '%s'.",
tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format(
"Unable to create directory '%s'.",
tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
protected void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
setEnabled(false);
final String msg = String.format(
"Unable to delete temporary file '%s'.",
tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
setEnabled(false);
final String msg = String.format(
"Unable to create directory '%s'.",
tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}
@@ -253,13 +273,15 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
* Deletes any files extracted from the Wheel during analysis.
*/
@Override
public void close() {
public void closeAnalyzer() {
if (tempFileLocation != null && tempFileLocation.exists()) {
LOGGER.debug("Attempting to delete temporary files");
final boolean success = FileUtils.delete(tempFileLocation);
if (!success) {
LOGGER.warn(
"Failed to delete some temporary files, see the log for more details");
if (!success && tempFileLocation.exists()) {
final String[] l = tempFileLocation.list();
if (l != null && l.length > 0) {
LOGGER.warn("Failed to delete some temporary files, see the log for more details");
}
}
}
}
@@ -269,10 +291,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param file a reference to the manifest/properties file
* @throws AnalysisException thrown when there is an error
*/
private static void collectWheelMetadata(Dependency dependency, File file)
throws AnalysisException {
private static void collectWheelMetadata(Dependency dependency, File file) {
final InternetHeaders headers = getManifestProperties(file);
addPropertyToEvidence(headers, dependency.getVersionEvidence(),
"Version", Confidence.HIGHEST);
@@ -313,7 +333,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns a list of files that match the given filter, this does not recursively scan the directory.
* Returns a list of files that match the given filter, this does not
* recursively scan the directory.
*
* @param folder the folder to filter
* @param filter the filter to apply to the files in the directory
@@ -339,20 +360,20 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
if (null == manifest) {
LOGGER.debug("Manifest file not found.");
} else {
try {
result.load(new AutoCloseInputStream(new BufferedInputStream(
new FileInputStream(manifest))));
} catch (MessagingException e) {
LOGGER.warn(e.getMessage(), e);
} catch (FileNotFoundException e) {
try (InputStream in = new BufferedInputStream(new FileInputStream(manifest))) {
result.load(in);
} catch (MessagingException | FileNotFoundException e) {
LOGGER.warn(e.getMessage(), e);
} catch (IOException ex) {
LOGGER.warn(ex.getMessage(), ex);
}
}
return result;
}
/**
* Retrieves the next temporary destingation directory for extracting an archive.
* Retrieves the next temporary destination directory for extracting an
* archive.
*
* @return a directory
* @throws AnalysisException thrown if unable to create temporary directory
@@ -363,7 +384,7 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
// getting an exception for some directories not being able to be
// created; might be because the directory already exists?
do {
dirCount += 1;
final int dirCount = DIR_COUNT.incrementAndGet();
directory = new File(tempFileLocation, String.valueOf(dirCount));
} while (directory.exists());
if (!directory.mkdirs()) {

View File

@@ -28,23 +28,22 @@ import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze a Python package, and collect information that can be used to determine the associated CPE.
* Used to analyze a Python package, and collect information that can be used to
* determine the associated CPE.
*
* @author Dale Visser <dvisser@ida.org>
* @author Dale Visser
*/
@Experimental
public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
/**
@@ -53,12 +52,6 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
private static final int REGEX_OPTIONS = Pattern.DOTALL
| Pattern.CASE_INSENSITIVE;
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory
.getLogger(PythonPackageAnalyzer.class);
/**
* Filename extensions for files to be analyzed.
*/
@@ -150,10 +143,10 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
/**
* No-op initializer implementation.
*
* @throws Exception never thrown
* @throws InitializationException never thrown
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// Nothing to do here.
}
@@ -174,36 +167,38 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
final File file = dependency.getActualFile();
final File parent = file.getParentFile();
final String parentName = parent.getName();
boolean found = false;
if (INIT_PY_FILTER.accept(file)) {
for (final File sourcefile : parent.listFiles(PY_FILTER)) {
found |= analyzeFileContents(dependency, sourcefile);
}
}
if (found) {
//by definition, the containing folder of __init__.py is considered the package, even the file is empty:
//"The __init__.py files are required to make Python treat the directories as containing packages"
//see section "6.4 Packages" from https://docs.python.org/2/tutorial/modules.html;
dependency.setDisplayFileName(parentName + "/__init__.py");
dependency.getProductEvidence().addEvidence(file.getName(),
"PackageName", parentName, Confidence.MEDIUM);
"PackageName", parentName, Confidence.HIGHEST);
final File[] fileList = parent.listFiles(PY_FILTER);
if (fileList != null) {
for (final File sourceFile : fileList) {
analyzeFileContents(dependency, sourceFile);
}
}
} else {
// copy, alter and set in case some other thread is iterating over
final List<Dependency> deps = new ArrayList<Dependency>(
engine.getDependencies());
deps.remove(dependency);
engine.setDependencies(deps);
engine.getDependencies().remove(dependency);
}
}
/**
* This should gather information from leading docstrings, file comments, and assignments to __version__, __title__,
* __summary__, __uri__, __url__, __home*page__, __author__, and their all caps equivalents.
* This should gather information from leading docstrings, file comments,
* and assignments to __version__, __title__, __summary__, __uri__, __url__,
* __home*page__, __author__, and their all caps equivalents.
*
* @param dependency the dependency being analyzed
* @param file the file name to analyze
@@ -214,7 +209,7 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
throws AnalysisException {
String contents;
try {
contents = FileUtils.readFileToString(file).trim();
contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim();
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
@@ -238,14 +233,10 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
.getVendorEvidence();
found |= gatherEvidence(AUTHOR_PATTERN, contents, source,
vendorEvidence, "SourceAuthor", Confidence.MEDIUM);
try {
found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence,
source, "URL", contents);
found |= gatherHomePageEvidence(HOMEPAGE_PATTERN,
vendorEvidence, source, "HomePage", contents);
} catch (MalformedURLException e) {
LOGGER.warn(e.getMessage());
}
found |= gatherHomePageEvidence(URI_PATTERN, vendorEvidence,
source, "URL", contents);
found |= gatherHomePageEvidence(HOMEPAGE_PATTERN,
vendorEvidence, source, "HomePage", contents);
}
return found;
}
@@ -281,11 +272,10 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
* @param name the name of the evidence
* @param contents the home page URL
* @return true if evidence was collected; otherwise false
* @throws MalformedURLException thrown if the URL is malformed
*/
private boolean gatherHomePageEvidence(Pattern pattern,
EvidenceCollection evidence, String source, String name,
String contents) throws MalformedURLException {
String contents) {
final Matcher matcher = pattern.matcher(contents);
boolean found = false;
if (matcher.find()) {
@@ -299,7 +289,8 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Gather evidence from a Python source file usin the given string assignment regex pattern.
* Gather evidence from a Python source file using the given string
* assignment regex pattern.
*
* @param pattern to scan contents with
* @param contents of Python source file

View File

@@ -0,0 +1,494 @@
/*
* 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) 2015 Institute for Defense Analyses. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Reference;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
* bundle-audit tool.
*
* @author Dale Visser
*/
@Experimental
public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Ruby Bundle Audit Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.PRE_INFORMATION_COLLECTION;
/**
* The filter defining which files will be analyzed.
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addFilenames("Gemfile.lock").build();
/**
* Name.
*/
public static final String NAME = "Name: ";
/**
* Version.
*/
public static final String VERSION = "Version: ";
/**
* Advisory.
*/
public static final String ADVISORY = "Advisory: ";
/**
* Criticality.
*/
public static final String CRITICALITY = "Criticality: ";
/**
* The DAL.
*/
private CveDB cvedb;
/**
* @return a filter that accepts files named Gemfile.lock
*/
@Override
protected FileFilter getFileFilter() {
return FILTER;
}
/**
* Launch bundle-audit.
*
* @param folder directory that contains bundle audit
* @return a handle to the process
* @throws AnalysisException thrown when there is an issue launching bundle
* audit
*/
private Process launchBundleAudit(File folder) throws AnalysisException {
if (!folder.isDirectory()) {
throw new AnalysisException(String.format("%s should have been a directory.", folder.getAbsolutePath()));
}
final List<String> args = new ArrayList<>();
final String bundleAuditPath = Settings.getString(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH);
File bundleAudit = null;
if (bundleAuditPath != null) {
bundleAudit = new File(bundleAuditPath);
if (!bundleAudit.isFile()) {
LOGGER.warn("Supplied `bundleAudit` path is incorrect: " + bundleAuditPath);
bundleAudit = null;
}
}
args.add(bundleAudit != null && bundleAudit.isFile() ? bundleAudit.getAbsolutePath() : "bundle-audit");
args.add("check");
args.add("--verbose");
final ProcessBuilder builder = new ProcessBuilder(args);
builder.directory(folder);
try {
LOGGER.info("Launching: " + args + " from " + folder);
return builder.start();
} catch (IOException ioe) {
throw new AnalysisException("bundle-audit initialization failure; this error can be ignored if you are not analyzing Ruby. "
+ "Otherwise ensure that bundle-audit is installed and the path to bundle audit is correctly specified", ioe);
}
}
/**
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a
* temporary location.
*
* @throws InitializationException if anything goes wrong
*/
@Override
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
cvedb = CveDB.getInstance();
} catch (DatabaseException ex) {
LOGGER.warn("Exception opening the database");
LOGGER.debug("error", ex);
setEnabled(false);
throw new InitializationException("Error connecting to the database", ex);
}
// Now, need to see if bundle-audit actually runs from this location.
Process process = null;
try {
process = launchBundleAudit(Settings.getTempDirectory());
} catch (AnalysisException ae) {
setEnabled(false);
final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME);
throw new InitializationException(msg, ae);
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex);
}
final int exitValue;
try {
exitValue = process.waitFor();
} catch (InterruptedException ex) {
setEnabled(false);
final String msg = String.format("Bundle-audit process was interrupted. Disabling %s", ANALYZER_NAME);
throw new InitializationException(msg);
}
if (0 == exitValue) {
setEnabled(false);
final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue);
throw new InitializationException(msg);
} else {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"))) {
if (!reader.ready()) {
LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME);
setEnabled(false);
throw new InitializationException("Bundle-audit error stream unexpectedly not ready.");
} else {
final String line = reader.readLine();
if (line == null || !line.contains("Errno::ENOENT")) {
LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line);
setEnabled(false);
throw new InitializationException("Unexpected bundle-audit output.");
}
}
} catch (UnsupportedEncodingException ex) {
setEnabled(false);
throw new InitializationException("Unexpected bundle-audit encoding.", ex);
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to read bundle-audit output.", ex);
}
}
if (isEnabled()) {
LOGGER.info(ANALYZER_NAME + " is enabled. It is necessary to manually run \"bundle-audit update\" "
+ "occasionally to keep its database up to date.");
}
}
/**
* Closes the data source.
*/
@Override
public void closeAnalyzer() {
if (cvedb != null) {
cvedb.close();
cvedb = null;
}
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED;
}
/**
* If {@link #analyzeDependency(Dependency, Engine)} is called, then we have
* successfully initialized, and it will be necessary to disable
* {@link RubyGemspecAnalyzer}.
*/
private boolean needToDisableGemspecAnalyzer = true;
/**
* Determines if the analyzer can analyze the given file type.
*
* @param dependency the dependency to determine if it can analyze
* @param engine the dependency-check engine
* @throws AnalysisException thrown if there is an analysis exception.
*/
@Override
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
if (needToDisableGemspecAnalyzer) {
boolean failed = true;
final String className = RubyGemspecAnalyzer.class.getName();
for (FileTypeAnalyzer analyzer : engine.getFileTypeAnalyzers()) {
if (analyzer instanceof RubyBundlerAnalyzer) {
((RubyBundlerAnalyzer) analyzer).setEnabled(false);
LOGGER.info("Disabled " + RubyBundlerAnalyzer.class.getName() + " to avoid noisy duplicate results.");
} else if (analyzer instanceof RubyGemspecAnalyzer) {
((RubyGemspecAnalyzer) analyzer).setEnabled(false);
LOGGER.info("Disabled " + className + " to avoid noisy duplicate results.");
failed = false;
}
}
if (failed) {
LOGGER.warn("Did not find " + className + '.');
}
needToDisableGemspecAnalyzer = false;
}
final File parentFile = dependency.getActualFile().getParentFile();
final Process process = launchBundleAudit(parentFile);
final int exitValue;
try {
exitValue = process.waitFor();
} catch (InterruptedException ie) {
throw new AnalysisException("bundle-audit process interrupted", ie);
}
if (exitValue < 0 || exitValue > 1) {
final String msg = String.format("Unexpected exit code from bundle-audit process; exit code: %s", exitValue);
throw new AnalysisException(msg);
}
try {
try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"))) {
while (errReader.ready()) {
final String error = errReader.readLine();
LOGGER.warn(error);
}
}
try (BufferedReader rdr = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))) {
processBundlerAuditOutput(dependency, engine, rdr);
}
} catch (IOException ioe) {
LOGGER.warn("bundle-audit failure", ioe);
}
}
/**
* Processes the bundler audit output.
*
* @param original the dependency
* @param engine the dependency-check engine
* @param rdr the reader of the report
* @throws IOException thrown if the report cannot be read.
*/
private void processBundlerAuditOutput(Dependency original, Engine engine, BufferedReader rdr) throws IOException {
final String parentName = original.getActualFile().getParentFile().getName();
final String fileName = original.getFileName();
final String filePath = original.getFilePath();
Dependency dependency = null;
Vulnerability vulnerability = null;
String gem = null;
final Map<String, Dependency> map = new HashMap<>();
boolean appendToDescription = false;
while (rdr.ready()) {
final String nextLine = rdr.readLine();
if (null == nextLine) {
break;
} else if (nextLine.startsWith(NAME)) {
appendToDescription = false;
gem = nextLine.substring(NAME.length());
if (!map.containsKey(gem)) {
map.put(gem, createDependencyForGem(engine, parentName, fileName, filePath, gem));
}
dependency = map.get(gem);
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
} else if (nextLine.startsWith(VERSION)) {
vulnerability = createVulnerability(parentName, dependency, gem, nextLine);
} else if (nextLine.startsWith(ADVISORY)) {
setVulnerabilityName(parentName, dependency, vulnerability, nextLine);
} else if (nextLine.startsWith(CRITICALITY)) {
addCriticalityToVulnerability(parentName, vulnerability, nextLine);
} else if (nextLine.startsWith("URL: ")) {
addReferenceToVulnerability(parentName, vulnerability, nextLine);
} else if (nextLine.startsWith("Description:")) {
appendToDescription = true;
if (null != vulnerability) {
vulnerability.setDescription("*** Vulnerability obtained from bundle-audit verbose report. "
+ "Title link may not work. CPE below is guessed. CVSS score is estimated (-1.0 "
+ " indicates unknown). See link below for full details. *** ");
}
} else if (appendToDescription && null != vulnerability) {
vulnerability.setDescription(vulnerability.getDescription() + nextLine + "\n");
}
}
}
/**
* Sets the vulnerability name.
*
* @param parentName the parent name
* @param dependency the dependency
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void setVulnerabilityName(String parentName, Dependency dependency, Vulnerability vulnerability, String nextLine) {
final String advisory = nextLine.substring((ADVISORY.length()));
if (null != vulnerability) {
vulnerability.setName(advisory);
}
if (null != dependency) {
dependency.getVulnerabilities().add(vulnerability); // needed to wait for vulnerability name to avoid NPE
}
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
/**
* Adds a reference to the vulnerability.
*
* @param parentName the parent name
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void addReferenceToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
final String url = nextLine.substring(("URL: ").length());
if (null != vulnerability) {
final Reference ref = new Reference();
ref.setName(vulnerability.getName());
ref.setSource("bundle-audit");
ref.setUrl(url);
vulnerability.getReferences().add(ref);
}
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
/**
* Adds the criticality to the vulnerability
*
* @param parentName the parent name
* @param vulnerability the vulnerability
* @param nextLine the line to parse
*/
private void addCriticalityToVulnerability(String parentName, Vulnerability vulnerability, String nextLine) {
if (null != vulnerability) {
final String criticality = nextLine.substring(CRITICALITY.length()).trim();
float score = -1.0f;
Vulnerability v = null;
try {
v = cvedb.getVulnerability(vulnerability.getName());
} catch (DatabaseException ex) {
LOGGER.debug("Unable to look up vulnerability {}", vulnerability.getName());
}
if (v != null) {
score = v.getCvssScore();
} else if ("High".equalsIgnoreCase(criticality)) {
score = 8.5f;
} else if ("Medium".equalsIgnoreCase(criticality)) {
score = 5.5f;
} else if ("Low".equalsIgnoreCase(criticality)) {
score = 2.0f;
}
vulnerability.setCvssScore(score);
}
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
}
/**
* Creates a vulnerability.
*
* @param parentName the parent name
* @param dependency the dependency
* @param gem the gem name
* @param nextLine the line to parse
* @return the vulnerability
*/
private Vulnerability createVulnerability(String parentName, Dependency dependency, String gem, String nextLine) {
Vulnerability vulnerability = null;
if (null != dependency) {
final String version = nextLine.substring(VERSION.length());
dependency.getVersionEvidence().addEvidence(
"bundler-audit",
"Version",
version,
Confidence.HIGHEST);
vulnerability = new Vulnerability(); // don't add to dependency until we have name set later
vulnerability.setMatchedCPE(
String.format("cpe:/a:%1$s_project:%1$s:%2$s::~~~ruby~~", gem, version),
null);
vulnerability.setCvssAccessVector("-");
vulnerability.setCvssAccessComplexity("-");
vulnerability.setCvssAuthentication("-");
vulnerability.setCvssAvailabilityImpact("-");
vulnerability.setCvssConfidentialityImpact("-");
vulnerability.setCvssIntegrityImpact("-");
}
LOGGER.debug(String.format("bundle-audit (%s): %s", parentName, nextLine));
return vulnerability;
}
/**
* Creates the dependency based off of the gem.
*
* @param engine the engine used for scanning
* @param parentName the gem parent
* @param fileName the file name
* @param filePath the file path
* @param gem the gem name
* @return the dependency to add
* @throws IOException thrown if a temporary gem file could not be written
*/
private Dependency createDependencyForGem(Engine engine, String parentName, String fileName, String filePath, String gem) throws IOException {
final File gemFile = new File(Settings.getTempDirectory(), gem + "_Gemfile.lock");
if (!gemFile.createNewFile()) {
throw new IOException("Unable to create temporary gem file");
}
final String displayFileName = String.format("%s%c%s:%s", parentName, File.separatorChar, fileName, gem);
FileUtils.write(gemFile, displayFileName, Charset.defaultCharset()); // unique contents to avoid dependency bundling
final Dependency dependency = new Dependency(gemFile);
dependency.getProductEvidence().addEvidence("bundler-audit", "Name", gem, Confidence.HIGHEST);
dependency.setDisplayFileName(displayFileName);
dependency.setFileName(fileName);
dependency.setFilePath(filePath);
engine.getDependencies().add(dependency);
return dependency;
}
}

View File

@@ -0,0 +1,141 @@
/*
* 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) 2016 IBM Corporation. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.FilenameFilter;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
/**
* This analyzer accepts the fully resolved .gemspec created by the Ruby bundler
* (http://bundler.io) for better evidence results. It also tries to resolve the
* dependency packagePath to where the gem is actually installed. Then during
* the {@link org.owasp.dependencycheck.analyzer.AnalysisPhase#PRE_FINDING_ANALYSIS}
* {@link DependencyMergingAnalyzer} will merge two .gemspec dependencies
* together if <code>Dependency.getPackagePath()</code> are the same.
*
* Ruby bundler creates new .gemspec files under a folder called
* "specifications" at deploy time, in addition to the original .gemspec files
* from source. The bundler generated .gemspec files always contain fully
* resolved attributes thus provide more accurate evidences, whereas the
* original .gemspec from source often contain variables for attributes that
* can't be used for evidences.
*
* Note this analyzer share the same
* {@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_RUBY_GEMSPEC_ENABLED}
* as {@link RubyGemspecAnalyzer}, so it will enabled/disabled with
* {@link RubyGemspecAnalyzer}.
*
* @author Bianca Jiang (https://twitter.com/biancajiang)
*/
@Experimental
public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Ruby Bundler Analyzer";
/**
* Folder name that contains .gemspec files created by "bundle install"
*/
private static final String SPECIFICATIONS = "specifications";
/**
* Folder name that contains the gems by "bundle install"
*/
private static final String GEMS = "gems";
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Only accept *.gemspec files generated by "bundle install --deployment"
* under "specifications" folder.
*
* @param pathname the path name to test
* @return true if the analyzer can process the given file; otherwise false
*/
@Override
public boolean accept(File pathname) {
boolean accepted = super.accept(pathname);
if (accepted) {
final File parentDir = pathname.getParentFile();
accepted = parentDir != null && parentDir.getName().equals(SPECIFICATIONS);
}
return accepted;
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
super.analyzeDependency(dependency, engine);
//find the corresponding gem folder for this .gemspec stub by "bundle install --deployment"
final File gemspecFile = dependency.getActualFile();
final String gemFileName = gemspecFile.getName();
final String gemName = gemFileName.substring(0, gemFileName.lastIndexOf(".gemspec"));
final File specificationsDir = gemspecFile.getParentFile();
if (specificationsDir != null && specificationsDir.getName().equals(SPECIFICATIONS) && specificationsDir.exists()) {
final File parentDir = specificationsDir.getParentFile();
if (parentDir != null && parentDir.exists()) {
final File gemsDir = new File(parentDir, GEMS);
if (gemsDir.exists()) {
final File[] matchingFiles = gemsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.equals(gemName);
}
});
if (matchingFiles != null && matchingFiles.length > 0) {
final String gemPath = matchingFiles[0].getAbsolutePath();
if (dependency.getActualFilePath().equals(dependency.getFilePath())) {
if (gemPath != null) {
dependency.setPackagePath(gemPath);
}
} else {
//.gemspec's actualFilePath and filePath are different when it's from a compressed file
//in which case actualFilePath is the temp directory used by decompression.
//packagePath should use the filePath of the identified gem file in "gems" folder
final File gemspecStub = new File(dependency.getFilePath());
final File specDir = gemspecStub.getParentFile();
if (specDir != null && specDir.getName().equals(SPECIFICATIONS)) {
final File gemsDir2 = new File(specDir.getParentFile(), GEMS);
final File packageDir = new File(gemsDir2, gemName);
dependency.setPackagePath(packageDir.getAbsolutePath());
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,249 @@
/*
* 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) 2015 Institute for Defense Analyses. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used to analyze Ruby Gem specifications and collect information that can be
* used to determine the associated CPE. Regular expressions are used to parse
* the well-defined Ruby syntax that forms the specification.
*
* @author Dale Visser
*/
@Experimental
public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(RubyGemspecAnalyzer.class);
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Ruby Gemspec Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The gemspec file extension.
*/
private static final String GEMSPEC = "gemspec";
/**
* The file filter containing the list of file extensions that can be
* analyzed.
*/
private static final FileFilter FILTER = FileFilterBuilder.newInstance().addExtensions(GEMSPEC).build();
//TODO: support Rakefile
//= FileFilterBuilder.newInstance().addExtensions(GEMSPEC).addFilenames("Rakefile").build();
/**
* The name of the version file.
*/
private static final String VERSION_FILE_NAME = "VERSION";
/**
* @return a filter that accepts files matching the glob pattern, *.gemspec
*/
@Override
protected FileFilter getFileFilter() {
return FILTER;
}
@Override
protected void initializeFileTypeAnalyzer() throws InitializationException {
// NO-OP
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED;
}
/**
* The capture group #1 is the block variable.
*/
private static final Pattern GEMSPEC_BLOCK_INIT = Pattern.compile("Gem::Specification\\.new\\s+?do\\s+?\\|(.+?)\\|");
@Override
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
String contents;
try {
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
}
final Matcher matcher = GEMSPEC_BLOCK_INIT.matcher(contents);
if (matcher.find()) {
contents = contents.substring(matcher.end());
final String blockVariable = matcher.group(1);
final EvidenceCollection vendor = dependency.getVendorEvidence();
final EvidenceCollection product = dependency.getProductEvidence();
final String name = addStringEvidence(product, contents, blockVariable, "name", "name", Confidence.HIGHEST);
if (!name.isEmpty()) {
vendor.addEvidence(GEMSPEC, "name_project", name + "_project", Confidence.LOW);
}
addStringEvidence(product, contents, blockVariable, "summary", "summary", Confidence.LOW);
addStringEvidence(vendor, contents, blockVariable, "author", "authors?", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "email", "emails?", Confidence.MEDIUM);
addStringEvidence(vendor, contents, blockVariable, "homepage", "homepage", Confidence.HIGHEST);
addStringEvidence(vendor, contents, blockVariable, "license", "licen[cs]es?", Confidence.HIGHEST);
final String value = addStringEvidence(dependency.getVersionEvidence(), contents,
blockVariable, "version", "version", Confidence.HIGHEST);
if (value.length() < 1) {
addEvidenceFromVersionFile(dependency.getActualFile(), dependency.getVersionEvidence());
}
}
setPackagePath(dependency);
}
/**
* Adds the specified evidence to the given evidence collection.
*
* @param evidences the collection to add the evidence to
* @param contents the evidence contents
* @param blockVariable the variable
* @param field the field
* @param fieldPattern the field pattern
* @param confidence the confidence of the evidence
* @return the evidence string value added
*/
private String addStringEvidence(EvidenceCollection evidences, String contents,
String blockVariable, String field, String fieldPattern, Confidence confidence) {
String value = "";
//capture array value between [ ]
final Matcher arrayMatcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?\\[(.*?)\\]", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
if (arrayMatcher.find()) {
final String arrayValue = arrayMatcher.group(1);
value = arrayValue.replaceAll("['\"]", "").trim(); //strip quotes
} else { //capture single value between quotes
final Matcher matcher = Pattern.compile(
String.format("\\s*?%s\\.%s\\s*?=\\s*?(['\"])(.*?)\\1", blockVariable, fieldPattern), Pattern.CASE_INSENSITIVE).matcher(contents);
if (matcher.find()) {
value = matcher.group(2);
}
}
if (value.length() > 0) {
evidences.addEvidence(GEMSPEC, field, value, confidence);
}
return value;
}
/**
* Adds evidence from the version file.
*
* @param dependencyFile the dependency being analyzed
* @param versionEvidences the version evidence
*/
private void addEvidenceFromVersionFile(File dependencyFile, EvidenceCollection versionEvidences) {
final File parentDir = dependencyFile.getParentFile();
if (parentDir != null) {
final File[] matchingFiles = parentDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.contains(VERSION_FILE_NAME);
}
});
if (matchingFiles == null) {
return;
}
for (File f : matchingFiles) {
try {
final List<String> lines = FileUtils.readLines(f, Charset.defaultCharset());
if (lines.size() == 1) { //TODO other checking?
final String value = lines.get(0).trim();
versionEvidences.addEvidence(GEMSPEC, "version", value, Confidence.HIGH);
}
} catch (IOException e) {
LOGGER.debug("Error reading gemspec", e);
}
}
}
}
/**
* Sets the package path on the dependency.
*
* @param dep the dependency to alter
*/
private void setPackagePath(Dependency dep) {
final File file = new File(dep.getFilePath());
final String parent = file.getParent();
if (parent != null) {
dep.setPackagePath(parent);
}
}
}

View File

@@ -0,0 +1,192 @@
/*
* 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) 2016 IBM Corporation. All Rights Reserved.
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
/**
* This analyzer is used to analyze the SWIFT Package Manager
* (https://swift.org/package-manager/). It collects information about a package
* from Package.swift files.
*
* @author Bianca Jiang (https://twitter.com/biancajiang)
*/
@Experimental
public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "SWIFT Package Manager Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION;
/**
* The file name to scan.
*/
public static final String SPM_FILE_NAME = "Package.swift";
/**
* Filter that detects files named "package.json".
*/
private static final FileFilter SPM_FILE_FILTER = FileFilterBuilder.newInstance().addFilenames(SPM_FILE_NAME).build();
/**
* The capture group #1 is the block variable. e.g. "import
* PackageDescription let package = Package( name: "Gloss" )"
*/
private static final Pattern SPM_BLOCK_PATTERN = Pattern.compile("let[^=]+=\\s*Package\\s*\\(\\s*([^)]*)\\s*\\)", Pattern.DOTALL);
/**
* Returns the FileFilter
*
* @return the FileFilter
*/
@Override
protected FileFilter getFileFilter() {
return SPM_FILE_FILTER;
}
@Override
protected void initializeFileTypeAnalyzer() {
// NO-OP
}
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED;
}
@Override
protected void analyzeDependency(Dependency dependency, Engine engine)
throws AnalysisException {
String contents;
try {
contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset());
} catch (IOException e) {
throw new AnalysisException(
"Problem occurred while reading dependency file.", e);
}
final Matcher matcher = SPM_BLOCK_PATTERN.matcher(contents);
if (matcher.find()) {
final String packageDescription = matcher.group(1);
if (packageDescription.isEmpty()) {
return;
}
final EvidenceCollection product = dependency.getProductEvidence();
final EvidenceCollection vendor = dependency.getVendorEvidence();
//SPM is currently under development for SWIFT 3. Its current metadata includes package name and dependencies.
//Future interesting metadata: version, license, homepage, author, summary, etc.
final String name = addStringEvidence(product, packageDescription, "name", "name", Confidence.HIGHEST);
if (name != null && !name.isEmpty()) {
vendor.addEvidence(SPM_FILE_NAME, "name_project", name, Confidence.HIGHEST);
}
}
setPackagePath(dependency);
}
/**
* Extracts evidence from the package description and adds it to the given
* evidence collection.
*
* @param evidences the evidence collection to update
* @param packageDescription the text to extract evidence from
* @param field the name of the field being searched for
* @param fieldPattern the field pattern within the contents to search for
* @param confidence the confidence level of the evidence if found
* @return the string that was added as evidence
*/
private String addStringEvidence(EvidenceCollection evidences,
String packageDescription, String field, String fieldPattern, Confidence confidence) {
String value = "";
final Matcher matcher = Pattern.compile(
String.format("%s *:\\s*\"([^\"]*)", fieldPattern), Pattern.DOTALL).matcher(packageDescription);
if (matcher.find()) {
value = matcher.group(1);
}
if (value != null) {
value = value.trim();
if (value.length() > 0) {
evidences.addEvidence(SPM_FILE_NAME, field, value, confidence);
}
}
return value;
}
/**
* Sets the package path on the given dependency.
*
* @param dep the dependency to update
*/
private void setPackagePath(Dependency dep) {
final File file = new File(dep.getFilePath());
final String parent = file.getParent();
if (parent != null) {
dep.setPackagePath(parent);
}
}
}

View File

@@ -0,0 +1,167 @@
/*
* 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.analyzer;
import java.util.Iterator;
import java.util.Objects;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This analyzer attempts to filter out erroneous version numbers collected.
* Initially, this will focus on JAR files that contain a POM version number
* that matches the file name - if identified all other version information will
* be removed.
*
* @author Jeremy Long
*/
public class VersionFilterAnalyzer extends AbstractAnalyzer {
//<editor-fold defaultstate="collapsed" desc="Constants">
/**
* Evidence source.
*/
private static final String FILE = "file";
/**
* Evidence source.
*/
private static final String POM = "pom";
/**
* Evidence source.
*/
private static final String NEXUS = "nexus";
/**
* Evidence source.
*/
private static final String CENTRAL = "central";
/**
* Evidence source.
*/
private static final String MANIFEST = "Manifest";
/**
* Evidence name.
*/
private static final String VERSION = "version";
/**
* Evidence name.
*/
private static final String IMPLEMENTATION_VERSION = "Implementation-Version";
/**
* The name of the analyzer.
*/
private static final String ANALYZER_NAME = "Version Filter Analyzer";
/**
* The phase that this analyzer is intended to run in.
*/
private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.POST_INFORMATION_COLLECTION;
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Standard implementation of Analyzer">
/**
* Returns the name of the analyzer.
*
* @return the name of the analyzer.
*/
@Override
public String getName() {
return ANALYZER_NAME;
}
/**
* Returns the phase that the analyzer is intended to run in.
*
* @return the phase that the analyzer is intended to run in.
*/
@Override
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* Returns the setting key to determine if the analyzer is enabled.
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_VERSION_FILTER_ENABLED;
}
//</editor-fold>
/**
* The Logger for use throughout the class
*/
private static final Logger LOGGER = LoggerFactory.getLogger(VersionFilterAnalyzer.class);
/**
* The HintAnalyzer uses knowledge about a dependency to add additional
* information to help in identification of identifiers or vulnerabilities.
*
* @param dependency The dependency being analyzed
* @param engine The scanning engine
* @throws AnalysisException is thrown if there is an exception analyzing
* the dependency.
*/
@Override
protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
String fileVersion = null;
String pomVersion = null;
String manifestVersion = null;
for (Evidence e : dependency.getVersionEvidence()) {
if (FILE.equals(e.getSource()) && VERSION.equals(e.getName())) {
fileVersion = e.getValue(Boolean.FALSE);
} else if ((NEXUS.equals(e.getSource()) || CENTRAL.equals(e.getSource())
|| POM.equals(e.getSource())) && VERSION.equals(e.getName())) {
pomVersion = e.getValue(Boolean.FALSE);
} else if (MANIFEST.equals(e.getSource()) && IMPLEMENTATION_VERSION.equals(e.getName())) {
manifestVersion = e.getValue(Boolean.FALSE);
}
}
//ensure we have at least two not null
if (((fileVersion == null ? 0 : 1) + (pomVersion == null ? 0 : 1) + (manifestVersion == null ? 0 : 1)) > 1) {
final DependencyVersion dvFile = new DependencyVersion(fileVersion);
final DependencyVersion dvPom = new DependencyVersion(pomVersion);
final DependencyVersion dvManifest = new DependencyVersion(manifestVersion);
final boolean fileMatch = Objects.equals(dvFile, dvPom) || Objects.equals(dvFile, dvManifest);
final boolean manifestMatch = Objects.equals(dvManifest, dvPom) || Objects.equals(dvManifest, dvFile);
final boolean pomMatch = Objects.equals(dvPom, dvFile) || Objects.equals(dvPom, dvManifest);
if (fileMatch || manifestMatch || pomMatch) {
LOGGER.debug("filtering evidence from {}", dependency.getFileName());
final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
final Iterator<Evidence> itr = versionEvidence.iterator();
while (itr.hasNext()) {
final Evidence e = itr.next();
if (!(pomMatch && VERSION.equals(e.getName())
&& (NEXUS.equals(e.getSource()) || CENTRAL.equals(e.getSource()) || POM.equals(e.getSource())))
&& !(fileMatch && VERSION.equals(e.getName()) && FILE.equals(e.getSource()))
&& !(manifestMatch && MANIFEST.equals(e.getSource()) && IMPLEMENTATION_VERSION.equals(e.getName()))) {
itr.remove();
}
}
}
}
}
}

View File

@@ -20,11 +20,13 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
/**
* The suppression analyzer processes an externally defined XML document that complies with the suppressions.xsd schema.
* Any identified Vulnerability entries within the dependencies that match will be removed.
* The suppression analyzer processes an externally defined XML document that
* complies with the suppressions.xsd schema. Any identified Vulnerability
* entries within the dependencies that match will be removed.
*
* @author Jeremy Long
*/
@@ -59,10 +61,29 @@ public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyze
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* <p>
* Returns the setting key to determine if the analyzer is enabled.</p>
*
* @return the key for the analyzer's enabled property
*/
@Override
protected String getAnalyzerEnabledSettingKey() {
return Settings.KEYS.ANALYZER_VULNERABILITY_SUPPRESSION_ENABLED;
}
//</editor-fold>
/**
* Analyzes a dependency's vulnerabilities against the configured CVE
* suppressions.
*
* @param dependency the dependency being analyzed
* @param engine a reference to the engine orchestrating the analysis
* @throws AnalysisException thrown if there is an error during analysis
*/
@Override
public void analyze(final Dependency dependency, final Engine engine) throws AnalysisException {
protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException {
if (getRules() == null || getRules().size() <= 0) {
return;

View File

@@ -24,17 +24,20 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.URLConnectionFactory;
import org.owasp.dependencycheck.utils.XmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Class of methods to search Maven Central via Central.
@@ -51,7 +54,7 @@ public class CentralSearch {
/**
* Whether to use the Proxy when making requests
*/
private boolean useProxy;
private final boolean useProxy;
/**
* Used for logging.
@@ -61,8 +64,8 @@ public class CentralSearch {
/**
* Creates a NexusSearch for the given repository URL.
*
* @param rootURL the URL of the repository on which searches should execute. Only parameters are added to this (so it should
* end in /select)
* @param rootURL the URL of the repository on which searches should
* execute. Only parameters are added to this (so it should end in /select)
*/
public CentralSearch(URL rootURL) {
this.rootURL = rootURL;
@@ -76,21 +79,23 @@ public class CentralSearch {
}
/**
* Searches the configured Central URL for the given sha1 hash. If the artifact is found, a <code>MavenArtifact</code> is
* populated with the GAV.
* Searches the configured Central URL for the given sha1 hash. If the
* artifact is found, a <code>MavenArtifact</code> is populated with the
* GAV.
*
* @param sha1 the SHA-1 hash string for which to search
* @return the populated Maven GAV.
* @throws IOException if it's unable to connect to the specified repository or if the specified artifact is not found.
* @throws IOException if it's unable to connect to the specified repository
* or if the specified artifact is not found.
*/
public List<MavenArtifact> searchSha1(String sha1) throws IOException {
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
throw new IllegalArgumentException("Invalid SHA1 format");
}
List<MavenArtifact> result = null;
final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1));
LOGGER.debug("Searching Central url {}", url.toString());
LOGGER.debug("Searching Central url {}", url);
// Determine if we need to use a proxy. The rules:
// 1) If the proxy is set, AND the setting is set to true, use the proxy
@@ -108,15 +113,14 @@ public class CentralSearch {
if (conn.getResponseCode() == 200) {
boolean missing = false;
try {
final DocumentBuilder builder = DocumentBuilderFactory
.newInstance().newDocumentBuilder();
final DocumentBuilder builder = XmlUtils.buildSecureDocumentBuilder();
final Document doc = builder.parse(conn.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
final String numFound = xpath.evaluate("/response/result/@numFound", doc);
if ("0".equals(numFound)) {
missing = true;
} else {
final ArrayList<MavenArtifact> result = new ArrayList<MavenArtifact>();
result = new ArrayList<>();
final NodeList docs = (NodeList) xpath.evaluate("/response/result/doc", doc, XPathConstants.NODESET);
for (int i = 0; i < docs.getLength(); i++) {
final String g = xpath.evaluate("./str[@name='g']", docs.item(i));
@@ -124,11 +128,11 @@ public class CentralSearch {
final String a = xpath.evaluate("./str[@name='a']", docs.item(i));
LOGGER.trace("ArtifactId: {}", a);
final String v = xpath.evaluate("./str[@name='v']", docs.item(i));
NodeList atts = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
NodeList attributes = (NodeList) xpath.evaluate("./arr[@name='ec']/str", docs.item(i), XPathConstants.NODESET);
boolean pomAvailable = false;
boolean jarAvailable = false;
for (int x = 0; x < atts.getLength(); x++) {
final String tmp = xpath.evaluate(".", atts.item(x));
for (int x = 0; x < attributes.getLength(); x++) {
final String tmp = xpath.evaluate(".", attributes.item(x));
if (".pom".equals(tmp)) {
pomAvailable = true;
} else if (".jar".equals(tmp)) {
@@ -136,24 +140,20 @@ public class CentralSearch {
}
}
atts = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET);
attributes = (NodeList) xpath.evaluate("./arr[@name='tags']/str", docs.item(i), XPathConstants.NODESET);
boolean useHTTPS = false;
for (int x = 0; x < atts.getLength(); x++) {
final String tmp = xpath.evaluate(".", atts.item(x));
for (int x = 0; x < attributes.getLength(); x++) {
final String tmp = xpath.evaluate(".", attributes.item(x));
if ("https".equals(tmp)) {
useHTTPS = true;
}
}
LOGGER.trace("Version: {}", v);
result.add(new MavenArtifact(g, a, v, jarAvailable, pomAvailable, useHTTPS));
}
return result;
}
} catch (Throwable e) {
// Anything else is jacked up XML stuff that we really can't recover
// from well
} catch (ParserConfigurationException | IOException | SAXException | XPathExpressionException e) {
// Anything else is jacked up XML stuff that we really can't recover from well
throw new IOException(e.getMessage(), e);
}
@@ -162,10 +162,9 @@ public class CentralSearch {
}
} else {
LOGGER.debug("Could not connect to Central received response code: {} {}",
conn.getResponseCode(), conn.getResponseMessage());
conn.getResponseCode(), conn.getResponseMessage());
throw new IOException("Could not connect to Central");
}
return null;
return result;
}
}

View File

@@ -1,6 +1,6 @@
/**
*
* Contains classes related to searching Maven Central.<br/><br/>
* Contains classes related to searching Maven Central.<br><br>
*
* These are used to abstract Maven Central searching away from OWASP Dependency Check so they can be reused elsewhere.
*/

View File

@@ -0,0 +1,110 @@
/*
* 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) 2015 The OWASP Foundation. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.composer;
/**
* Represents a dependency (GAV, right now) from a Composer dependency.
*
* @author colezlaw
*/
public final class ComposerDependency {
/**
* The group
*/
private final String group;
/**
* The project
*/
private final String project;
/**
* The version
*/
private final String version;
/**
* Create a ComposerDependency from group, project, and version.
*
* @param group the group
* @param project the project
* @param version the version
*/
public ComposerDependency(String group, String project, String version) {
this.group = group;
this.project = project;
this.version = version;
}
/**
* Get the group.
*
* @return the group
*/
public String getGroup() {
return group;
}
/**
* Get the project.
*
* @return the project
*/
public String getProject() {
return project;
}
/**
* Get the version.
*
* @return the version
*/
public String getVersion() {
return version;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ComposerDependency)) {
return false;
}
final ComposerDependency that = (ComposerDependency) o;
if (group != null ? !group.equals(that.group) : that.group != null) {
return false;
}
if (project != null ? !project.equals(that.project) : that.project != null) {
return false;
}
return !(version != null ? !version.equals(that.version) : that.version != null);
}
@Override
public int hashCode() {
int result = group != null ? group.hashCode() : 0;
result = 31 * result + (project != null ? project.hashCode() : 0);
result = 31 * result + (version != null ? version.hashCode() : 0);
return result;
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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) 2015 The OWASP Foundation. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.composer;
/**
* Represents an exception when handling a composer.json or composer.lock file. Generally used to wrap a downstream exception.
*
* @author colezlaw
*/
public class ComposerException extends RuntimeException {
/**
* The serial version UID for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a ComposerException with default message.
*/
public ComposerException() {
super();
}
/**
* Creates a ComposerException with the specified message.
*
* @param message the exception message
*/
public ComposerException(String message) {
super(message);
}
/**
* Creates a Composer exception with the specified message and cause.
*
* @param message the message
* @param cause the underlying cause
*/
public ComposerException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,118 @@
/*
* 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) 2015 The OWASP Foundation. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.composer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.stream.JsonParsingException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected.
*
* @author colezlaw
*/
public class ComposerLockParser {
/**
* The JsonReader for parsing JSON
*/
private final JsonReader jsonReader;
/**
* The List of ComposerDependencies found
*/
private final List<ComposerDependency> composerDependencies;
/**
* The LOGGER
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ComposerLockParser.class);
/**
* Creates a ComposerLockParser from a JsonReader and an InputStream.
*
* @param inputStream the InputStream to parse
*/
public ComposerLockParser(InputStream inputStream) {
LOGGER.info("Creating a ComposerLockParser");
this.jsonReader = Json.createReader(inputStream);
this.composerDependencies = new ArrayList<>();
}
/**
* Process the input stream to create the list of dependencies.
*/
public void process() {
LOGGER.info("Beginning Composer lock processing");
try {
final JsonObject composer = jsonReader.readObject();
if (composer.containsKey("packages")) {
LOGGER.debug("Found packages");
final JsonArray packages = composer.getJsonArray("packages");
for (JsonObject pkg : packages.getValuesAs(JsonObject.class)) {
if (pkg.containsKey("name")) {
final String groupName = pkg.getString("name");
if (groupName.indexOf('/') >= 0 && groupName.indexOf('/') <= groupName.length() - 1) {
if (pkg.containsKey("version")) {
final String group = groupName.substring(0, groupName.indexOf('/'));
final String project = groupName.substring(groupName.indexOf('/') + 1);
String version = pkg.getString("version");
// Some version numbers begin with v - which doesn't end up matching CPE's
if (version.startsWith("v")) {
version = version.substring(1);
}
LOGGER.debug("Got package {}/{}/{}", group, project, version);
composerDependencies.add(new ComposerDependency(group, project, version));
} else {
LOGGER.debug("Group/package {} does not have a version", groupName);
}
} else {
LOGGER.debug("Got a dependency with no name");
}
}
}
}
} catch (JsonParsingException jsonpe) {
throw new ComposerException("Error parsing stream", jsonpe);
} catch (JsonException jsone) {
throw new ComposerException("Error reading stream", jsone);
} catch (IllegalStateException ise) {
throw new ComposerException("Illegal state in composer stream", ise);
} catch (ClassCastException cce) {
throw new ComposerException("Not exactly composer lock", cce);
}
}
/**
* Gets the list of dependencies.
*
* @return the list of dependencies
*/
public List<ComposerDependency> getDependencies() {
return composerDependencies;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Model elements for PHP Composer files
*/
package org.owasp.dependencycheck.data.composer;

View File

@@ -38,7 +38,6 @@ import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.RAMDirectory;
import org.owasp.dependencycheck.data.lucene.FieldAnalyzer;
import org.owasp.dependencycheck.data.lucene.LuceneUtils;
import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
@@ -48,8 +47,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within the NVD
* CVE data.
* An in memory lucene index that contains the vendor/product combinations from
* the CPE (application) identifiers within the NVD CVE data.
*
* @author Jeremy Long
*/
@@ -63,21 +62,6 @@ public final class CpeMemoryIndex {
* singleton instance.
*/
private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex();
/**
* private constructor for singleton.
*/
private CpeMemoryIndex() {
}
/**
* Gets the singleton instance of the CpeMemoryIndex.
*
* @return the instance of the CpeMemoryIndex
*/
public static CpeMemoryIndex getInstance() {
return INSTANCE;
}
/**
* The in memory Lucene index.
*/
@@ -101,11 +85,30 @@ public final class CpeMemoryIndex {
/**
* The search field analyzer for the product field.
*/
private SearchFieldAnalyzer productSearchFieldAnalyzer;
private SearchFieldAnalyzer productFieldAnalyzer;
/**
* The search field analyzer for the vendor field.
*/
private SearchFieldAnalyzer vendorSearchFieldAnalyzer;
private SearchFieldAnalyzer vendorFieldAnalyzer;
/**
* A flag indicating whether or not the index is open.
*/
private boolean openState = false;
/**
* private constructor for singleton.
*/
private CpeMemoryIndex() {
}
/**
* Gets the singleton instance of the CpeMemoryIndex.
*
* @return the instance of the CpeMemoryIndex
*/
public static CpeMemoryIndex getInstance() {
return INSTANCE;
}
/**
* Creates and loads data into an in memory index.
@@ -130,10 +133,6 @@ public final class CpeMemoryIndex {
}
}
}
/**
* A flag indicating whether or not the index is open.
*/
private boolean openState = false;
/**
* returns whether or not the index is open.
@@ -144,51 +143,20 @@ public final class CpeMemoryIndex {
return openState;
}
/**
* Creates the indexing analyzer for the CPE Index.
*
* @return the CPE Analyzer.
*/
@SuppressWarnings("unchecked")
private Analyzer createIndexingAnalyzer() {
final Map fieldAnalyzers = new HashMap();
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers);
}
/**
* Creates an Analyzer for searching the CPE Index.
*
* @return the CPE Analyzer.
*/
@SuppressWarnings("unchecked")
private Analyzer createSearchingAnalyzer() {
final Map<String, Analyzer> fieldAnalyzers = new HashMap<String, Analyzer>();
final Map<String, Analyzer> fieldAnalyzers = new HashMap<>();
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
productSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
fieldAnalyzers.put(Fields.PRODUCT, productSearchFieldAnalyzer);
fieldAnalyzers.put(Fields.VENDOR, vendorSearchFieldAnalyzer);
productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
fieldAnalyzers.put(Fields.PRODUCT, productFieldAnalyzer);
fieldAnalyzers.put(Fields.VENDOR, vendorFieldAnalyzer);
return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers);
}
/**
* Saves a CPE IndexEntry into the Lucene index.
*
* @param vendor the vendor to index
* @param product the product to index
* @param indexWriter the index writer to write the entry into
* @throws CorruptIndexException is thrown if the index is corrupt
* @throws IOException is thrown if an IOException occurs
*/
public void saveEntry(String vendor, String product, IndexWriter indexWriter) throws CorruptIndexException, IOException {
final Document doc = new Document();
final Field v = new TextField(Fields.VENDOR, vendor, Field.Store.YES);
final Field p = new TextField(Fields.PRODUCT, product, Field.Store.YES);
doc.add(v);
doc.add(p);
indexWriter.addDocument(doc);
return new PerFieldAnalyzerWrapper(new KeywordAnalyzer(), fieldAnalyzers);
}
/**
@@ -223,54 +191,47 @@ public final class CpeMemoryIndex {
* @throws IndexException thrown if there is an issue creating the index
*/
private void buildIndex(CveDB cve) throws IndexException {
Analyzer analyzer = null;
IndexWriter indexWriter = null;
try {
analyzer = createIndexingAnalyzer();
final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer);
indexWriter = new IndexWriter(index, conf);
try {
final Set<Pair<String, String>> data = cve.getVendorProductList();
for (Pair<String, String> pair : data) {
saveEntry(pair.getLeft(), pair.getRight(), indexWriter);
try (Analyzer analyzer = createSearchingAnalyzer();
IndexWriter indexWriter = new IndexWriter(index, new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer))) {
// Tip: reuse the Document and Fields for performance...
// See "Re-use Document and Field instances" from
// http://wiki.apache.org/lucene-java/ImproveIndexingSpeed
final Document doc = new Document();
final Field v = new TextField(Fields.VENDOR, Fields.VENDOR, Field.Store.YES);
final Field p = new TextField(Fields.PRODUCT, Fields.PRODUCT, Field.Store.YES);
doc.add(v);
doc.add(p);
final Set<Pair<String, String>> data = cve.getVendorProductList();
for (Pair<String, String> pair : data) {
if (pair.getLeft() != null && pair.getRight() != null) {
v.setStringValue(pair.getLeft());
p.setStringValue(pair.getRight());
indexWriter.addDocument(doc);
resetFieldAnalyzer();
}
} catch (DatabaseException ex) {
LOGGER.debug("", ex);
throw new IndexException("Error reading CPE data", ex);
}
indexWriter.commit();
indexWriter.close(true);
} catch (DatabaseException ex) {
LOGGER.debug("", ex);
throw new IndexException("Error reading CPE data", ex);
} catch (CorruptIndexException ex) {
throw new IndexException("Unable to close an in-memory index", ex);
} catch (IOException ex) {
throw new IndexException("Unable to close an in-memory index", ex);
} finally {
if (indexWriter != null) {
try {
try {
indexWriter.commit();
} finally {
indexWriter.close(true);
}
} catch (CorruptIndexException ex) {
throw new IndexException("Unable to close an in-memory index", ex);
} catch (IOException ex) {
throw new IndexException("Unable to close an in-memory index", ex);
}
if (analyzer != null) {
analyzer.close();
}
}
}
}
/**
* Resets the searching analyzers
* Resets the product and vendor field analyzers.
*/
private void resetSearchingAnalyzer() {
if (productSearchFieldAnalyzer != null) {
productSearchFieldAnalyzer.clear();
private void resetFieldAnalyzer() {
if (productFieldAnalyzer != null) {
productFieldAnalyzer.clear();
}
if (vendorSearchFieldAnalyzer != null) {
vendorSearchFieldAnalyzer.clear();
if (vendorFieldAnalyzer != null) {
vendorFieldAnalyzer.clear();
}
}
@@ -281,14 +242,17 @@ public final class CpeMemoryIndex {
* @param maxQueryResults the maximum number of documents to return
* @return the TopDocs found by the search
* @throws ParseException thrown when the searchString is invalid
* @throws IOException is thrown if there is an issue with the underlying Index
* @throws IOException is thrown if there is an issue with the underlying
* Index
*/
public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
public synchronized TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
if (searchString == null || searchString.trim().isEmpty()) {
throw new ParseException("Query is null or empty");
}
LOGGER.debug(searchString);
resetFieldAnalyzer();
final Query query = queryParser.parse(searchString);
return indexSearcher.search(query, maxQueryResults);
return search(query, maxQueryResults);
}
/**
@@ -300,8 +264,8 @@ public final class CpeMemoryIndex {
* @throws CorruptIndexException thrown if the Index is corrupt
* @throws IOException thrown if there is an IOException
*/
public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
resetSearchingAnalyzer();
public synchronized TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
resetFieldAnalyzer();
return indexSearcher.search(query, maxQueryResults);
}

View File

@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.cpe;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import org.apache.commons.lang3.StringUtils;
/**
* A CPE entry containing the name, vendor, product, and version.
@@ -31,7 +32,7 @@ public class IndexEntry implements Serializable {
/**
* the serial version uid.
*/
static final long serialVersionUID = 8011924485946326934L;
private static final long serialVersionUID = 8011924485946326934L;
/**
* The vendor name.
*/
@@ -48,7 +49,7 @@ public class IndexEntry implements Serializable {
*/
public String getDocumentId() {
if (documentId == null && vendor != null && product != null) {
documentId = vendor + ":" + product;
documentId = vendor + ':' + product;
}
return documentId;
}
@@ -143,7 +144,8 @@ public class IndexEntry implements Serializable {
*/
public void parseName(String cpeName) throws UnsupportedEncodingException {
if (cpeName != null && cpeName.length() > 7) {
final String[] data = cpeName.substring(7).split(":");
final String cpeNameWithoutPrefix = cpeName.substring(7);
final String[] data = StringUtils.split(cpeNameWithoutPrefix, ':');
if (data.length >= 1) {
vendor = URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8");
if (data.length >= 2) {
@@ -172,10 +174,7 @@ public class IndexEntry implements Serializable {
if ((this.vendor == null) ? (other.vendor != null) : !this.vendor.equals(other.vendor)) {
return false;
}
if ((this.product == null) ? (other.product != null) : !this.product.equals(other.product)) {
return false;
}
return true;
return !((this.product == null) ? (other.product != null) : !this.product.equals(other.product));
}
/**

View File

@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;
/**
*
@@ -45,21 +46,19 @@ public final class CweDB {
/**
* A HashMap of the CWE data.
*/
private static final HashMap<String, String> CWE = loadData();
private static final Map<String, String> CWE = loadData();
/**
* Loads a HashMap containing the CWE data from a resource found in the jar.
*
* @return a HashMap of CWE data
*/
private static HashMap<String, String> loadData() {
ObjectInputStream oin = null;
try {
final String filePath = "data/cwe.hashmap.serialized";
final InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
oin = new ObjectInputStream(input);
@SuppressWarnings("unchecked")
final HashMap<String, String> ret = (HashMap<String, String>) oin.readObject();
private static Map<String, String> loadData() {
final String filePath = "data/cwe.hashmap.serialized";
try (InputStream input = CweDB.class.getClassLoader().getResourceAsStream(filePath);
ObjectInputStream oin = new ObjectInputStream(input)) {
final Map<String, String> ret = (HashMap<String, String>) oin.readObject();
return ret;
} catch (ClassNotFoundException ex) {
LOGGER.warn("Unable to load CWE data. This should not be an issue.");
@@ -67,14 +66,6 @@ public final class CweDB {
} catch (IOException ex) {
LOGGER.warn("Unable to load CWE data due to an IO Error. This should not be an issue.");
LOGGER.debug("", ex);
} finally {
if (oin != null) {
try {
oin.close();
} catch (IOException ex) {
LOGGER.trace("", ex);
}
}
}
return null;
}

View File

@@ -32,12 +32,12 @@ public class CweHandler extends DefaultHandler {
/**
* a HashMap containing the CWE data.
*/
private final HashMap<String, String> cwe = new HashMap<String, String>();
private final HashMap<String, String> cwe = new HashMap<>();
/**
* Returns the HashMap of CWE entries (CWE-ID, Full CWE Name).
*
* @return a HashMap of CWE entries <String, String>
* @return a HashMap of CWE entries &lt;String, String&gt;
*/
public HashMap<String, String> getCwe() {
return cwe;

View File

@@ -63,7 +63,7 @@ public abstract class AbstractTokenizingFilter extends TokenFilter {
*/
public AbstractTokenizingFilter(TokenStream stream) {
super(stream);
tokens = new LinkedList<String>();
tokens = new LinkedList<>();
}
/**

View File

@@ -29,11 +29,15 @@ import org.apache.lucene.util.Version;
/**
* <p>
* A Lucene Analyzer that utilizes the WhitespaceTokenizer, WordDelimiterFilter, LowerCaseFilter, and StopFilter. The intended
* purpose of this Analyzer is to index the CPE fields vendor and product.</p>
* A Lucene Analyzer that utilizes the WhitespaceTokenizer, WordDelimiterFilter,
* LowerCaseFilter, and StopFilter. The intended purpose of this Analyzer is to
* index the CPE fields vendor and product.</p>
*
* @author Jeremy Long
* @deprecated the field analyzer should not be used, instead use the
* SearchFieldAnalyzer so that the token analyzing filter is used.
*/
@Deprecated
public class FieldAnalyzer extends Analyzer {
/**

View File

@@ -77,6 +77,7 @@ public final class LuceneUtils {
case '*':
case '?':
case ':':
case '/':
case '\\': //it is supposed to fall through here
buf.append('\\');
default:
@@ -93,17 +94,12 @@ public final class LuceneUtils {
* @return the escaped text.
*/
public static String escapeLuceneQuery(final CharSequence text) {
if (text == null) {
return null;
}
int size = text.length();
size = size >> 1;
final int size = text.length() << 1;
final StringBuilder buf = new StringBuilder(size);
appendEscapedLuceneQuery(buf, text);
return buf.toString();
}
}

View File

@@ -27,7 +27,7 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
* <p>
* Takes a TokenStream and adds additional tokens by concatenating pairs of words.</p>
* <p>
* <b>Example:</b> "Spring Framework Core" -> "Spring SpringFramework Framework FrameworkCore Core".</p>
* <b>Example:</b> "Spring Framework Core" -&gt; "Spring SpringFramework Framework FrameworkCore Core".</p>
*
* @author Jeremy Long
*/
@@ -71,12 +71,12 @@ public final class TokenPairConcatenatingFilter extends TokenFilter {
*/
public TokenPairConcatenatingFilter(TokenStream stream) {
super(stream);
words = new LinkedList<String>();
words = new LinkedList<>();
}
/**
* Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by
* concatenating tokens with the previous token.
* Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by concatenating
* tokens with the previous token.
*
* @return whether or not we have hit the end of the TokenStream
* @throws IOException is thrown when an IOException occurs
@@ -112,8 +112,7 @@ public final class TokenPairConcatenatingFilter extends TokenFilter {
/**
* <p>
* Resets the Filter and clears any internal state data that may have been left-over from previous uses of the
* Filter.</p>
* Resets the Filter and clears any internal state data that may have been left-over from previous uses of the Filter.</p>
* <p>
* <b>If this Filter is re-used this method must be called between uses.</b></p>
*/
@@ -121,4 +120,43 @@ public final class TokenPairConcatenatingFilter extends TokenFilter {
previousWord = null;
words.clear();
}
/**
* Standard hash code implementation.
*
* @return the hash code
*/
@Override
public int hashCode() {
int hash = 3;
hash = 31 * hash + (this.termAtt != null ? this.termAtt.hashCode() : 0);
hash = 31 * hash + (this.previousWord != null ? this.previousWord.hashCode() : 0);
hash = 31 * hash + (this.words != null ? this.words.hashCode() : 0);
return hash;
}
/**
* Standard equals implementation.
*
* @param obj the object to compare
* @return true if the objects are equal; otherwise false.
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TokenPairConcatenatingFilter other = (TokenPairConcatenatingFilter) obj;
if (this.termAtt != other.termAtt && (this.termAtt == null || !this.termAtt.equals(other.termAtt))) {
return false;
}
if ((this.previousWord == null) ? (other.previousWord != null) : !this.previousWord.equals(other.previousWord)) {
return false;
}
return !(this.words != other.words && (this.words == null || !this.words.equals(other.words)));
}
}

View File

@@ -31,15 +31,17 @@ import org.slf4j.LoggerFactory;
* <p>
* Takes a TokenStream and splits or adds tokens to correctly index version numbers.</p>
* <p>
* <b>Example:</b> "3.0.0.RELEASE" -> "3 3.0 3.0.0 RELEASE 3.0.0.RELEASE".</p>
* <b>Example:</b> "3.0.0.RELEASE" -&gt; "3 3.0 3.0.0 RELEASE 3.0.0.RELEASE".</p>
*
* @author Jeremy Long
*/
public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(UrlTokenizingFilter.class);
/**
* Constructs a new VersionTokenizingFilter.
*
@@ -50,8 +52,8 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
}
/**
* Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by
* concatenating tokens with the previous token.
* Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by concatenating
* tokens with the previous token.
*
* @return whether or not we have hit the end of the TokenStream
* @throws IOException is thrown when an IOException occurs

View File

@@ -94,13 +94,13 @@ public class MavenArtifact {
}
if (jarAvailable) {
//org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
this.artifactUrl = base + groupId.replace('.', '/') + "/" + artifactId + "/"
+ version + "/" + artifactId + "-" + version + ".jar";
this.artifactUrl = base + groupId.replace('.', '/') + '/' + artifactId + '/'
+ version + '/' + artifactId + '-' + version + ".jar";
}
if (pomAvailable) {
//org/springframework/spring-core/3.2.0.RELEASE/spring-core-3.2.0.RELEASE.pom
this.pomUrl = base + groupId.replace('.', '/') + "/" + artifactId + "/"
+ version + "/" + artifactId + "-" + version + ".pom";
this.pomUrl = base + groupId.replace('.', '/') + '/' + artifactId + '/'
+ version + '/' + artifactId + '-' + version + ".pom";
}
}

Some files were not shown because too many files have changed in this diff Show More